From antocuni at codespeak.net Thu May 1 11:38:50 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 1 May 2008 11:38:50 +0200 (CEST) Subject: [pypy-svn] r54301 - in pypy/branch/oo-jit/pypy/jit: rainbow rainbow/test timeshifter Message-ID: <20080501093850.E579E2A01B2@codespeak.net> Author: antocuni Date: Thu May 1 11:38:48 2008 New Revision: 54301 Modified: pypy/branch/oo-jit/pypy/jit/rainbow/test/test_llinterp.py pypy/branch/oo-jit/pypy/jit/rainbow/typesystem.py pypy/branch/oo-jit/pypy/jit/timeshifter/rtimeshift.py Log: more translation fixes Modified: pypy/branch/oo-jit/pypy/jit/rainbow/test/test_llinterp.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/rainbow/test/test_llinterp.py (original) +++ pypy/branch/oo-jit/pypy/jit/rainbow/test/test_llinterp.py Thu May 1 11:38:48 2008 @@ -12,6 +12,14 @@ # for the individual tests see # ====> test_portal.py + def skip(self): + py.test.skip('in progress') + + test_dfa_compile = skip + test_dfa_compile2 = skip + test_dfa_compile3 = skip + + class TestLLInterpretedLLType(test_portal.TestPortalLLType): translate_support_code = True Modified: pypy/branch/oo-jit/pypy/jit/rainbow/typesystem.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/rainbow/typesystem.py (original) +++ pypy/branch/oo-jit/pypy/jit/rainbow/typesystem.py Thu May 1 11:38:48 2008 @@ -1,4 +1,6 @@ -from pypy.rpython.annlowlevel import base_ptr_lltype +from pypy.rpython.annlowlevel import base_ptr_lltype, base_obj_ootype +from pypy.rpython.annlowlevel import cast_instance_to_base_ptr +from pypy.rpython.annlowlevel import cast_instance_to_base_obj from pypy.rpython.lltypesystem import lltype, llmemory from pypy.rpython.ootypesystem import ootype @@ -27,6 +29,7 @@ name = 'lltype' ROOT_TYPE = llmemory.Address NULL_OBJECT = base_ptr_lltype()._defl() + cast_instance_to_base_ptr = staticmethod(cast_instance_to_base_ptr) def get_typeptr(self, obj): return obj.typeptr @@ -55,7 +58,8 @@ name = 'ootype' ROOT_TYPE = ootype.Object - NULL_OBJECT = ootype.NULL + NULL_OBJECT = base_obj_ootype()._defl() + cast_instance_to_base_ptr = staticmethod(cast_instance_to_base_obj) def get_typeptr(self, obj): return obj.meta Modified: pypy/branch/oo-jit/pypy/jit/timeshifter/rtimeshift.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/timeshifter/rtimeshift.py (original) +++ pypy/branch/oo-jit/pypy/jit/timeshifter/rtimeshift.py Thu May 1 11:38:48 2008 @@ -777,10 +777,10 @@ else: return ptr -def _cast_promotion_point_to_base_ptr(instance): +def _cast_promotion_point_to_base_ptr(jitstate, instance): assert isinstance(instance, PromotionPoint) if we_are_translated(): - return cast_instance_to_base_ptr(instance) + return jitstate.ts.cast_instance_to_base_ptr(instance) else: return instance @@ -846,7 +846,7 @@ pm = PromotionPoint(flexswitch, incoming_gv, jitstate.promotion_path) #debug_print(lltype.Void, "PROMOTE") - ll_pm = _cast_promotion_point_to_base_ptr(pm) + ll_pm = _cast_promotion_point_to_base_ptr(jitstate, pm) gv_pm = default_builder.rgenop.genconst(ll_pm) gv_switchvar = promotebox.genvar exceptiondesc = promotiondesc.exceptiondesc @@ -1282,7 +1282,7 @@ setexcvaluebox(self, evaluebox) def residual_exception(self, e): - self.residual_ll_exception(cast_instance_to_base_ptr(e)) + self.residual_ll_exception(self.ts.cast_instance_to_base_ptr(e)) def get_resuming(self): if self.frame.dispatchqueue is None: From docgok at codespeak.net Thu May 1 18:07:44 2008 From: docgok at codespeak.net (docgok at codespeak.net) Date: Thu, 1 May 2008 18:07:44 +0200 (CEST) Subject: [pypy-svn] r54308 - pypy/branch/io-improvements/pypy/translator/llvm Message-ID: <20080501160744.3D393169DFB@codespeak.net> Author: docgok Date: Thu May 1 18:07:43 2008 New Revision: 54308 Modified: pypy/branch/io-improvements/pypy/translator/llvm/opwriter.py Log: force_cast implementation for LLVM Modified: pypy/branch/io-improvements/pypy/translator/llvm/opwriter.py ============================================================================== --- pypy/branch/io-improvements/pypy/translator/llvm/opwriter.py (original) +++ pypy/branch/io-improvements/pypy/translator/llvm/opwriter.py Thu May 1 18:07:43 2008 @@ -139,6 +139,8 @@ self.cast_int_to_ptr(opr) else: self.cast_primitive(opr) + elif op.opname == 'force_cast': + self.cast_primitive(opr) else: meth = getattr(self, op.opname, None) if not meth: From bgola at codespeak.net Thu May 1 22:42:33 2008 From: bgola at codespeak.net (bgola at codespeak.net) Date: Thu, 1 May 2008 22:42:33 +0200 (CEST) Subject: [pypy-svn] r54309 - pypy/branch/2.5-features/pypy/interpreter/pyparser/data Message-ID: <20080501204233.82DE1498001@codespeak.net> Author: bgola Date: Thu May 1 22:42:31 2008 New Revision: 54309 Modified: pypy/branch/2.5-features/pypy/interpreter/pyparser/data/Grammar2.5 Log: supporting 2.5 grammar, almost working now Modified: pypy/branch/2.5-features/pypy/interpreter/pyparser/data/Grammar2.5 ============================================================================== --- pypy/branch/2.5-features/pypy/interpreter/pyparser/data/Grammar2.5 (original) +++ pypy/branch/2.5-features/pypy/interpreter/pyparser/data/Grammar2.5 Thu May 1 22:42:31 2008 @@ -62,9 +62,8 @@ 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] +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)* @@ -121,7 +120,7 @@ lambdef: 'lambda' [varargslist] ':' test trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME subscriptlist: subscript (',' subscript)* [','] -subscript: '.' '.' '.' | test | [test] ':' [test] [sliceop] +subscript: '.' '.' '.' | [test] ':' [test] [sliceop] | test sliceop: ':' [test] exprlist: expr (',' expr)* [','] testlist: test (',' test)* [','] From antocuni at codespeak.net Fri May 2 12:37:34 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 2 May 2008 12:37:34 +0200 (CEST) Subject: [pypy-svn] r54316 - in pypy/branch/oo-jit/pypy/rpython/ootypesystem: . test Message-ID: <20080502103734.08CF32A805F@codespeak.net> Author: antocuni Date: Fri May 2 12:37:32 2008 New Revision: 54316 Modified: pypy/branch/oo-jit/pypy/rpython/ootypesystem/ootype.py pypy/branch/oo-jit/pypy/rpython/ootypesystem/test/test_oortype.py Log: a hack; since pbc unbound methods are not supported in general, provide a way to build a wrapper that calls it, given the name Modified: pypy/branch/oo-jit/pypy/rpython/ootypesystem/ootype.py ============================================================================== --- pypy/branch/oo-jit/pypy/rpython/ootypesystem/ootype.py (original) +++ pypy/branch/oo-jit/pypy/rpython/ootypesystem/ootype.py Fri May 2 12:37:32 2008 @@ -1882,6 +1882,20 @@ ref.ll_set(obj) return ref +def build_unbound_method_wrapper(meth): + METH = typeOf(meth) + methname = meth._name + funcname = '%s_wrapper' % methname + nb_args = len(METH.ARGS) + arglist = ', '.join('a%d' % i for i in range(nb_args)) + ns = {'methname': methname} + code = py.code.Source(""" + def %s(self, %s): + m = getattr(self, methname) + return m(%s) + """ % (funcname, arglist, arglist)) + exec code.compile() in ns + return ns[funcname] Object = Object() NULL = _object(None) Modified: pypy/branch/oo-jit/pypy/rpython/ootypesystem/test/test_oortype.py ============================================================================== --- pypy/branch/oo-jit/pypy/rpython/ootypesystem/test/test_oortype.py (original) +++ pypy/branch/oo-jit/pypy/rpython/ootypesystem/test/test_oortype.py Fri May 2 12:37:32 2008 @@ -337,3 +337,16 @@ return oodowncast(A, c) py.test.raises(AnnotatorError, interpret, fn, [], type_system='ootype') + +def test_method_wrapper(): + L = List(Signed) + _, meth = L._lookup('ll_getitem_fast') + wrapper = build_unbound_method_wrapper(meth) + + def fn(): + lst = L.ll_newlist(1) + lst.ll_setitem_fast(0, 42) + return wrapper(lst, 0) + + res = interpret(fn, [], type_system='ootype') + assert res == 42 From antocuni at codespeak.net Fri May 2 14:01:59 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 2 May 2008 14:01:59 +0200 (CEST) Subject: [pypy-svn] r54317 - pypy/branch/oo-jit/pypy/rpython Message-ID: <20080502120159.0B6D8169E87@codespeak.net> Author: antocuni Date: Fri May 2 14:01:57 2008 New Revision: 54317 Modified: pypy/branch/oo-jit/pypy/rpython/annlowlevel.py Log: forgot to checkin this in in r54301; make cast_object_to_ptr and cast_base_ptr_to_instance ootype-friendly Modified: pypy/branch/oo-jit/pypy/rpython/annlowlevel.py ============================================================================== --- pypy/branch/oo-jit/pypy/rpython/annlowlevel.py (original) +++ pypy/branch/oo-jit/pypy/rpython/annlowlevel.py Fri May 2 14:01:57 2008 @@ -472,28 +472,51 @@ return cast_object_to_ptr(base_ptr_lltype(), instance) cast_instance_to_base_ptr._annspecialcase_ = 'specialize:argtype(0)' +def cast_instance_to_base_obj(instance): + return cast_object_to_ptr(base_obj_ootype(), instance) +cast_instance_to_base_obj._annspecialcase_ = 'specialize:argtype(0)' + def base_ptr_lltype(): from pypy.rpython.lltypesystem.rclass import OBJECTPTR return OBJECTPTR +def base_obj_ootype(): + from pypy.rpython.ootypesystem.rclass import OBJECT + return OBJECT + class CastObjectToPtrEntry(extregistry.ExtRegistryEntry): _about_ = cast_object_to_ptr def compute_result_annotation(self, s_PTR, s_object): assert s_PTR.is_constant() - assert isinstance(s_PTR.const, lltype.Ptr) - return annmodel.SomePtr(s_PTR.const) + if isinstance(s_PTR.const, lltype.Ptr): + return annmodel.SomePtr(s_PTR.const) + elif isinstance(s_PTR.const, ootype.Instance): + return annmodel.SomeOOInstance(s_PTR.const) + else: + assert False def specialize_call(self, hop): from pypy.rpython import rpbc PTR = hop.r_result.lowleveltype + if isinstance(PTR, lltype.Ptr): + T = lltype.Ptr + opname = 'cast_pointer' + null = lltype.nullptr(PTR.TO) + elif isinstance(PTR, ootype.Instance): + T = ootype.Instance + opname = 'ooupcast' + null = ootype.null(PTR) + else: + assert False + if isinstance(hop.args_r[1], rpbc.NoneFrozenPBCRepr): - return hop.inputconst(PTR, lltype.nullptr(PTR.TO)) + return hop.inputconst(PTR, null) v_arg = hop.inputarg(hop.args_r[1], arg=1) - assert isinstance(v_arg.concretetype, lltype.Ptr) + assert isinstance(v_arg.concretetype, T) hop.exception_cannot_occur() - return hop.genop('cast_pointer', [v_arg], - resulttype = PTR) + return hop.genop(opname, [v_arg], resulttype = PTR) + # ____________________________________________________________ @@ -510,13 +533,19 @@ def specialize_call(self, hop): v_arg = hop.inputarg(hop.args_r[1], arg=1) - assert isinstance(v_arg.concretetype, lltype.Ptr) + if isinstance(v_arg.concretetype, lltype.Ptr): + opname = 'cast_pointer' + elif isinstance(v_arg.concretetype, ootype.Instance): + opname = 'ooupcast' + else: + assert False hop.exception_cannot_occur() - return hop.genop('cast_pointer', [v_arg], + return hop.genop(opname, [v_arg], resulttype = hop.r_result.lowleveltype) # ____________________________________________________________ + def placeholder_sigarg(s): if s == "self": def expand(s_self, *args_s): From arigo at codespeak.net Fri May 2 15:13:08 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 2 May 2008 15:13:08 +0200 (CEST) Subject: [pypy-svn] r54323 - pypy/dist/pypy/translator/benchmark Message-ID: <20080502131308.425F0169E4C@codespeak.net> Author: arigo Date: Fri May 2 15:13:07 2008 New Revision: 54323 Modified: pypy/dist/pypy/translator/benchmark/bench-custom.py pypy/dist/pypy/translator/benchmark/result.py Log: For very long executable names, this displays the results more readably by splitting the table in two. Modified: pypy/dist/pypy/translator/benchmark/bench-custom.py ============================================================================== --- pypy/dist/pypy/translator/benchmark/bench-custom.py (original) +++ pypy/dist/pypy/translator/benchmark/bench-custom.py Fri May 2 15:13:07 2008 @@ -5,6 +5,8 @@ from pypy.translator.benchmark.benchmarks import BENCHMARKS import os, sys, time, pickle, re, py +SPLIT_TABLE = True # useful when executable names are very long + def get_executables(args): #sorted by revision number (highest first) exes = sorted(args, key=os.path.getmtime) r = [] @@ -52,17 +54,28 @@ pickle.dump(benchmark_result, open(options.picklefile, 'wb')) - stats = ['stat:st_mtime', 'exe_name', 'pypy_rev'] + exe_stats = ['stat:st_mtime', 'exe_name', 'pypy_rev'] + if not SPLIT_TABLE: + stats = exe_stats[:] + else: + stats = ['exe'] for b in benchmarks: stats.append('bench:'+b.name) if options.relto: relto = options.relto else: relto = full_pythons[0] - for row in benchmark_result.txt_summary(stats, - relto=relto, - filteron=lambda r: r.exe_name in exes): + kwds = {'relto': relto, + 'filteron' :lambda r: r.exe_name in exes, + } + for row in benchmark_result.txt_summary(stats, **kwds): print row + if SPLIT_TABLE: + print + print 'Reference:' + for row in benchmark_result.txt_summary(['exe'] + exe_stats, + **kwds): + print row if __name__ == '__main__': from optparse import OptionParser Modified: pypy/dist/pypy/translator/benchmark/result.py ============================================================================== --- pypy/dist/pypy/translator/benchmark/result.py (original) +++ pypy/dist/pypy/translator/benchmark/result.py Fri May 2 15:13:07 2008 @@ -68,6 +68,7 @@ return concretetable class BenchmarkResult(object): + IDS = {} def __init__(self, exe, max_results=10): self.max_results = max_results @@ -116,6 +117,10 @@ return_default = True if hasattr(self, stat): return getattr(self, stat) + if stat == 'exe': + myid = len(BenchmarkResult.IDS) + myid = BenchmarkResult.IDS.setdefault(self, myid) + return '[%s]' % myid statkind, statdetail = stat.split(':') if statkind == 'stat': return getattr(self.exe_stat, statdetail) From antocuni at codespeak.net Fri May 2 16:00:09 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 2 May 2008 16:00:09 +0200 (CEST) Subject: [pypy-svn] r54324 - in pypy/branch/oo-jit/pypy: annotation jit/codegen/llgraph jit/rainbow/test jit/timeshifter Message-ID: <20080502140009.C6211169ED2@codespeak.net> Author: antocuni Date: Fri May 2 16:00:08 2008 New Revision: 54324 Modified: pypy/branch/oo-jit/pypy/annotation/model.py pypy/branch/oo-jit/pypy/jit/codegen/llgraph/rgenop.py pypy/branch/oo-jit/pypy/jit/rainbow/test/test_llinterp.py pypy/branch/oo-jit/pypy/jit/timeshifter/oop.py Log: more translation fixes; skip tests that are known to fail Modified: pypy/branch/oo-jit/pypy/annotation/model.py ============================================================================== --- pypy/branch/oo-jit/pypy/annotation/model.py (original) +++ pypy/branch/oo-jit/pypy/annotation/model.py Fri May 2 16:00:08 2008 @@ -595,6 +595,8 @@ return s_val.ootype if isinstance(s_val, SomeOOStaticMeth): return s_val.method + if isinstance(s_val, SomeOOClass): + return s_val.ootype if isinstance(s_val, SomeInteriorPtr): p = s_val.ll_ptrtype if 0 in p.offsets: @@ -633,6 +635,8 @@ return SomeOOStaticMeth(T) elif T == ootype.Class: return SomeOOClass(ootype.ROOT) + elif T == ootype.Object: + return SomeOOObject() elif isinstance(T, ExternalType): return SomeExternalInstance(T._class_) elif isinstance(T, lltype.InteriorPtr): Modified: pypy/branch/oo-jit/pypy/jit/codegen/llgraph/rgenop.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/codegen/llgraph/rgenop.py (original) +++ pypy/branch/oo-jit/pypy/jit/codegen/llgraph/rgenop.py Fri May 2 16:00:08 2008 @@ -290,6 +290,11 @@ "genop_oononnull: bad currently_writing") return LLVar(llimpl.genop(self.b, 'oononnull', [gv_obj], gv_Bool.v)) + def genop_ooisnull(self, gv_obj): + ll_assert(self.rgenop.currently_writing is self, + "genop_ooisnull: bad currently_writing") + return LLVar(llimpl.genop(self.b, 'ooisnull', [gv_obj], gv_Bool.v)) + def genop_cast_int_to_ptr(self, gv_PTRTYPE, gv_int): ll_assert(self.rgenop.currently_writing is self, "genop_cast_int_to_ptr: bad currently_writing") Modified: pypy/branch/oo-jit/pypy/jit/rainbow/test/test_llinterp.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/rainbow/test/test_llinterp.py (original) +++ pypy/branch/oo-jit/pypy/jit/rainbow/test/test_llinterp.py Fri May 2 16:00:08 2008 @@ -18,6 +18,15 @@ test_dfa_compile = skip test_dfa_compile2 = skip test_dfa_compile3 = skip + test_multiple_portal_calls = skip + test_cast_ptr_to_int = skip + test_residual_red_call_with_promoted_exc = skip + test_residual_oop_raising = skip + test_simple_recursive_portal_call = skip + test_simple_recursive_portal_call2 = skip + test_recursive_portal_call = skip + test_indirect_call_voidargs = skip + test_vdict_and_vlist = skip Modified: pypy/branch/oo-jit/pypy/jit/timeshifter/oop.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/timeshifter/oop.py (original) +++ pypy/branch/oo-jit/pypy/jit/timeshifter/oop.py Fri May 2 16:00:08 2008 @@ -280,6 +280,9 @@ self.ARGS = [METH.SELFTYPE] + list(METH.ARGS) self.RESULT = METH.RESULT + wrapper = ootype.build_unbound_method_wrapper(meth) + self.fnptr = self.rtyper.annotate_helper_fn(wrapper, self.ARGS) + # we assume the number and position of the arguments are the # same as in the original oosend self.OOPARGTYPES = [self.SELFTYPE] + list(METH.ARGS) @@ -289,7 +292,6 @@ methname = methname.lstrip('ll_') self.method = 'oop_%s_method_%s' % (self.typename, methname) self.is_method = True - self.fnptr = meth class SendOopSpecDesc_list(SendOopSpecDesc): From antocuni at codespeak.net Fri May 2 16:18:51 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 2 May 2008 16:18:51 +0200 (CEST) Subject: [pypy-svn] r54325 - pypy/branch/oo-jit/pypy/translator/goal Message-ID: <20080502141851.C757B169EEF@codespeak.net> Author: antocuni Date: Fri May 2 16:18:51 2008 New Revision: 54325 Modified: pypy/branch/oo-jit/pypy/translator/goal/timing.py Log: don't crash on error because of missing tk attribute Modified: pypy/branch/oo-jit/pypy/translator/goal/timing.py ============================================================================== --- pypy/branch/oo-jit/pypy/translator/goal/timing.py (original) +++ pypy/branch/oo-jit/pypy/translator/goal/timing.py Fri May 2 16:18:51 2008 @@ -15,6 +15,7 @@ self.next_even = None self.timer = timer self.t0 = None + self.tk = None def start_event(self, event): now = self.timer() @@ -31,6 +32,8 @@ self.tk = now def ttime(self): + if self.tk is None: + return -1 return self.tk - self.t0 def pprint(self): From arigo at codespeak.net Fri May 2 16:49:48 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 2 May 2008 16:49:48 +0200 (CEST) Subject: [pypy-svn] r54326 - pypy/dist/pypy/config Message-ID: <20080502144948.9205D169EF4@codespeak.net> Author: arigo Date: Fri May 2 16:49:46 2008 New Revision: 54326 Modified: pypy/dist/pypy/config/pypyoption.py Log: Reintroduce for now optimized_list_getitem in faassen, because it still helps a bit. Modified: pypy/dist/pypy/config/pypyoption.py ============================================================================== --- pypy/dist/pypy/config/pypyoption.py (original) +++ pypy/dist/pypy/config/pypyoption.py Fri May 2 16:49:46 2008 @@ -315,6 +315,7 @@ # ("objspace.std.withfastslice", True), ("objspace.std.withprebuiltchar", True), ("objspace.std.builtinshortcut", True), + ("objspace.std.optimized_list_getitem", True), ("objspace.std.getattributeshortcut", True), ("translation.list_comprehension_operations",True), ], From arigo at codespeak.net Fri May 2 20:05:02 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 2 May 2008 20:05:02 +0200 (CEST) Subject: [pypy-svn] r54347 - in pypy/dist/pypy/objspace/std: . test Message-ID: <20080502180502.1CE6E169E6E@codespeak.net> Author: arigo Date: Fri May 2 20:05:02 2008 New Revision: 54347 Modified: pypy/dist/pypy/objspace/std/objecttype.py pypy/dist/pypy/objspace/std/test/test_userobject.py Log: Fix object.__repr__() to show the class' module name, as in CPython. Modified: pypy/dist/pypy/objspace/std/objecttype.py ============================================================================== --- pypy/dist/pypy/objspace/std/objecttype.py (original) +++ pypy/dist/pypy/objspace/std/objecttype.py Fri May 2 20:05:02 2008 @@ -9,7 +9,17 @@ def descr__repr__(space, w_obj): w = space.wrap - classname = space.str_w(space.getattr(space.type(w_obj), w("__name__"))) + w_type = space.type(w_obj) + classname = w_type.getname(space, '?') + w_module = w_type.lookup("__module__") + if w_module is not None: + try: + modulename = space.str_w(w_module) + except OperationError, e: + if not e.match(space, space.w_TypeError): + raise + else: + classname = '%s.%s' % (modulename, classname) return w_obj.getrepr(space, '%s object' % (classname,)) def descr__str__(space, w_obj): Modified: pypy/dist/pypy/objspace/std/test/test_userobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/test/test_userobject.py (original) +++ pypy/dist/pypy/objspace/std/test/test_userobject.py Fri May 2 20:05:02 2008 @@ -200,6 +200,13 @@ assert myint(3) - 5 == -2 assert 5 - myint(3) == 'rsub' + def test_repr(self): + class Foo(object): + pass + Foo.__module__ = 'a.b.c' + s = repr(Foo()) + assert s.startswith(' Author: bgola Date: Sat May 3 00:38:21 2008 New Revision: 54356 Added: pypy/branch/2.5-features/pypy/lib/app_test/test_defaultdict.py (contents, props changed) Modified: pypy/branch/2.5-features/pypy/lib/collections.py Log: defaultdict implementation in collections module Added: pypy/branch/2.5-features/pypy/lib/app_test/test_defaultdict.py ============================================================================== --- (empty file) +++ pypy/branch/2.5-features/pypy/lib/app_test/test_defaultdict.py Sat May 3 00:38:21 2008 @@ -0,0 +1,110 @@ +# defaultdict Tests +# from CPython2.5 + +import copy + +# for passing the test on top of 2.3 +from py.builtin import reversed +import pypy.lib.collections +pypy.lib.collections.reversed = reversed + +from pypy.lib.collections import defaultdict + +def foobar(): + return list + +class Test_defaultdict: + + def test_basic(self): + d1 = defaultdict() + assert d1.default_factory is None + d1.default_factory = list + d1[12].append(42) + assert d1 == {12: [42]} + d1[12].append(24) + assert d1 == {12: [42, 24]} + d1[13] + d1[14] + assert d1 == {12: [42, 24], 13: [], 14: []} + assert d1[12] is not d1[13] is not d1[14] + d2 = defaultdict(list, foo=1, bar=2) + assert d2.default_factory == list + assert d2 == {"foo": 1, "bar": 2} + assert d2["foo"] == 1 + assert d2["bar"] == 2 + assert d2[42] == [] + assert "foo" in d2 + assert "foo" in d2.keys() + assert "bar" in d2 + assert "bar" in d2.keys() + assert 42 in d2 + assert 42 in d2.keys() + assert 12 not in d2 + assert 12 not in d2.keys() + d2.default_factory = None + assert d2.default_factory == None + raises(KeyError, d2.__getitem__, 15) + raises(TypeError, defaultdict, 1) + + def test_missing(self): + d1 = defaultdict() + raises(KeyError, d1.__missing__, 42) + d1.default_factory = list + assert d1.__missing__(42) == [] + + def test_repr(self): + d1 = defaultdict() + assert d1.default_factory == None + assert repr(d1) == "defaultdict(None, {})" + d1[11] = 41 + assert repr(d1) == "defaultdict(None, {11: 41})" + d2 = defaultdict(int) + assert d2.default_factory == int + d2[12] = 42 + assert repr(d2), "defaultdict(, {12: 42})" + def foo(): return 43 + d3 = defaultdict(foo) + assert d3.default_factory is foo + d3[13] + assert repr(d3), "defaultdict(%s, {13: 43})" % repr(foo) + + def test_copy(self): + d1 = defaultdict() + d2 = d1.copy() + assert type(d2) == defaultdict + assert d2.default_factory == None + assert d2 == {} + d1.default_factory = list + d3 = d1.copy() + assert type(d3) == defaultdict + assert d3.default_factory == list + assert d3 == {} + d1[42] + d4 = d1.copy() + assert type(d4) == defaultdict + assert d4.default_factory == list + assert d4 == {42: []} + d4[12] + assert d4 == {42: [], 12: []} + + def test_shallow_copy(self): + d1 = defaultdict(foobar, {1: 1}) + d2 = copy.copy(d1) + assert d2.default_factory == foobar + assert d2 == d1 + d1.default_factory = list + d2 = copy.copy(d1) + assert d2.default_factory == list + assert d2 == d1 + + def test_deep_copy(self): + d1 = defaultdict(foobar, {1: [1]}) + d2 = copy.deepcopy(d1) + assert d2.default_factory == foobar + assert d2 == d1 + assert d1[1] is not d2[1] + d1.default_factory = list + d2 = copy.deepcopy(d1) + assert d2.default_factory == list + assert d2 == d1 + Modified: pypy/branch/2.5-features/pypy/lib/collections.py ============================================================================== --- pypy/branch/2.5-features/pypy/lib/collections.py (original) +++ pypy/branch/2.5-features/pypy/lib/collections.py Sat May 3 00:38:21 2008 @@ -308,4 +308,45 @@ def __len__(self): return self.counter - + +class defaultdict(dict): + + def __init__(self, *args, **kwds): + self.default_factory = None + if 'default_factory' in kwds: + self.default_factory = kwds.pop('default_factory') + elif len(args) > 0 and callable(args[0]): + self.default_factory = args[0] + args = args[1:] + super(defaultdict, self).__init__(*args, **kwds) + + def __missing__(self, key): + # from defaultdict docs + if self.default_factory is None: + raise KeyError((key,)) + self[key] = value = self.default_factory() + return value + + def __repr__(self): + return "defaultdict(%s, %s)" % (repr(self.default_factory), super(defaultdict, self).__repr__()) + + def copy(self): + return type(self)(self, default_factory=self.default_factory) + + def __copy__(self): + return self.copy() + + def __reduce__(self): + """ + __reduce__ must return a 5-tuple as follows: + + - factory function + - tuple of args for the factory function + - additional state (here None) + - sequence iterator (here None) + - dictionary iterator (yielding successive (key, value) pairs + + This API is used by pickle.py and copy.py. + """ + return (type(self), (self.default_factory,), None, None, self.iteritems()) + From antocuni at codespeak.net Sat May 3 15:36:12 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Sat, 3 May 2008 15:36:12 +0200 (CEST) Subject: [pypy-svn] r54362 - pypy/branch/oo-jit/pypy/jit/rainbow Message-ID: <20080503133612.AC6D716856A@codespeak.net> Author: antocuni Date: Sat May 3 15:36:10 2008 New Revision: 54362 Modified: pypy/branch/oo-jit/pypy/jit/rainbow/codewriter.py Log: remove the (hopefully) last direct references to lltype from codewriter Modified: pypy/branch/oo-jit/pypy/jit/rainbow/codewriter.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/rainbow/codewriter.py (original) +++ pypy/branch/oo-jit/pypy/jit/rainbow/codewriter.py Sat May 3 15:36:10 2008 @@ -368,17 +368,17 @@ def make_own_call_information(self, graph): ARGS = [v.concretetype for v in graph.getargs()] RESULT = graph.getreturnvar().concretetype - FUNCTYPE = lltype.FuncType(ARGS, RESULT) + FUNCTYPE = self.FuncType(ARGS, RESULT) colororder = make_colororder(graph, self.hannotator) owncalldesc = CallDesc(self.RGenOp, self.exceptiondesc, - lltype.Ptr(FUNCTYPE), colororder) + self.Ptr(FUNCTYPE), colororder) # detect the special ts_stub or ts_metacall graphs and replace # a real function pointer to them with a function pointer to # the graph they are stubs for if hasattr(graph, 'ts_stub_for'): graph = graph.ts_stub_for - ownfnptr = lltype.functionptr(FUNCTYPE, graph.name, graph=graph) + ownfnptr = self.functionptr(FUNCTYPE, graph.name, graph=graph) gv_ownfnptr = self.RGenOp.constPrebuiltGlobal(ownfnptr) return owncalldesc, gv_ownfnptr @@ -1635,6 +1635,9 @@ ExceptionDesc = exception.LLTypeExceptionDesc StructTypeDesc = rcontainer.StructTypeDesc + FuncType = staticmethod(lltype.FuncType) + Ptr = staticmethod(lltype.Ptr) + functionptr = staticmethod(lltype.functionptr) def cast_fnptr_to_root(self, fnptr): return llmemory.cast_ptr_to_adr(fnptr) @@ -1672,7 +1675,10 @@ ExceptionDesc = exception.OOTypeExceptionDesc StructTypeDesc = rcontainer.InstanceTypeDesc - + FuncType = staticmethod(ootype.StaticMethod) + Ptr = staticmethod(lambda x: x) + functionptr = staticmethod(ootype.static_meth) + def decompose_oosend(self, op): name = op.args[0].value opargs = op.args[1:] From antocuni at codespeak.net Sat May 3 15:46:10 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Sat, 3 May 2008 15:46:10 +0200 (CEST) Subject: [pypy-svn] r54366 - in pypy/branch/oo-jit/pypy: config translator translator/test Message-ID: <20080503134610.5F361168521@codespeak.net> Author: antocuni Date: Sat May 3 15:46:09 2008 New Revision: 54366 Modified: pypy/branch/oo-jit/pypy/config/translationoption.py pypy/branch/oo-jit/pypy/translator/driver.py pypy/branch/oo-jit/pypy/translator/test/test_driver.py Log: add the relevant tasks to driver to do --jit on ootype; fix test_driver Modified: pypy/branch/oo-jit/pypy/config/translationoption.py ============================================================================== --- pypy/branch/oo-jit/pypy/config/translationoption.py (original) +++ pypy/branch/oo-jit/pypy/config/translationoption.py Sat May 3 15:46:09 2008 @@ -31,13 +31,14 @@ "llvm": [("translation.type_system", "lltype"), ("translation.backendopt.raisingop2direct_call", True), ], - "cli": [("translation.type_system", "ootype")], + "cli": [("translation.type_system", "ootype"), + ("translation.jitbackend", "cli")], "jvm": [("translation.type_system", "ootype")], "js": [("translation.type_system", "ootype")], }, cmdline="-b --backend"), ChoiceOption("jitbackend", "Backent to use for JIT code generation", - ["ia32", "i386", "ppc"], cmdline="--jit-backend", + ["ia32", "i386", "ppc", "cli"], cmdline="--jit-backend", default=None), BoolOption("llvm_via_c", "compile llvm via C", default=False, cmdline="--llvm-via-c", Modified: pypy/branch/oo-jit/pypy/translator/driver.py ============================================================================== --- pypy/branch/oo-jit/pypy/translator/driver.py (original) +++ pypy/branch/oo-jit/pypy/translator/driver.py Sat May 3 15:46:09 2008 @@ -378,6 +378,14 @@ [RTYPE], "Backendopt before Hint-annotate") + def task_prehannotatebackendopt_ootype(self): + self.task_prehannotatebackendopt_lltype() + # + task_prehannotatebackendopt_ootype = taskdef( + task_prehannotatebackendopt_ootype, + [OOTYPE], + "Backendopt before Hint-annotate") + def task_hintannotate_lltype(self): from pypy.jit.hintannotator.model import OriginFlags from pypy.jit.hintannotator.model import SomeLLAbstractConstant @@ -416,30 +424,19 @@ ['prehannotatebackendopt_lltype'], "Hint-annotate") - def task_rainbow_lltype(self): - cpu = self.config.translation.jitbackend - if cpu is None: - from pypy.jit.codegen import detect_cpu - cpu = detect_cpu.autodetect() - if cpu == 'i386': - from pypy.jit.codegen.i386.rgenop import RI386GenOp as RGenOp - RGenOp.MC_SIZE = 32 * 1024 * 1024 - elif cpu == 'ia32': - from pypy.jit.codegen.ia32.rgenop import RI386GenOp as RGenOp - RGenOp.MC_SIZE = 32 * 1024 * 1024 - elif cpu == 'ppc': - from pypy.jit.codegen.ppc.rgenop import RPPCGenOp as RGenOp - RGenOp.MC_SIZE = 32 * 1024 * 1024 - else: - raise Exception('Unsuported cpu %r'%cpu) + def task_hintannotate_ootype(self): + self.task_hintannotate_lltype() + task_hintannotate_ootype = taskdef(task_hintannotate_ootype, + ['prehannotatebackendopt_ootype'], + "Hint-annotate") + def do_task_rainbow(self, RGenOp, BytecodeWriter): del self.hint_translator ha = self.hannotator t = self.translator rtyper = t.rtyper # make the bytecode and the rainbow interp - from pypy.jit.rainbow.codewriter import LLTypeBytecodeWriter - writer = LLTypeBytecodeWriter(t, ha, RGenOp, verbose=False) + writer = BytecodeWriter(t, ha, RGenOp, verbose=False) jitcode = writer.make_bytecode(self.portal_graph) if ha.policy.hotpath: from pypy.jit.rainbow.hotpath import HotRunnerDesc @@ -459,11 +456,40 @@ rewriter.rewrite(origportalgraph=self.orig_portal_graph, portalgraph=self.portal_graph, view=False) + + def task_rainbow_lltype(self): + from pypy.jit.rainbow.codewriter import LLTypeBytecodeWriter + cpu = self.config.translation.jitbackend + if cpu is None: + from pypy.jit.codegen import detect_cpu + cpu = detect_cpu.autodetect() + if cpu == 'i386': + from pypy.jit.codegen.i386.rgenop import RI386GenOp as RGenOp + RGenOp.MC_SIZE = 32 * 1024 * 1024 + elif cpu == 'ia32': + from pypy.jit.codegen.ia32.rgenop import RI386GenOp as RGenOp + RGenOp.MC_SIZE = 32 * 1024 * 1024 + elif cpu == 'ppc': + from pypy.jit.codegen.ppc.rgenop import RPPCGenOp as RGenOp + RGenOp.MC_SIZE = 32 * 1024 * 1024 + else: + raise Exception('Unsuported cpu %r'%cpu) + self.do_task_rainbow(RGenOp, LLTypeBytecodeWriter) # task_rainbow_lltype = taskdef(task_rainbow_lltype, ["hintannotate_lltype"], "Create Rainbow-Interpreter") + def task_rainbow_ootype(self): + from pypy.jit.rainbow.codewriter import OOTypeBytecodeWriter + from pypy.jit.codegen.cli.rgenop import RCliGenOp as RGenOp + cpu = self.config.translation.jitbackend + assert cpu == 'cli' + self.do_task_rainbow(RGenOp, OOTypeBytecodeWriter) + task_rainbow_ootype = taskdef(task_rainbow_ootype, + ["hintannotate_ootype"], + "Create Rainbow-Interpreter") + def task_backendopt_lltype(self): from pypy.translator.backendopt.all import backend_optimizations backend_optimizations(self.translator) Modified: pypy/branch/oo-jit/pypy/translator/test/test_driver.py ============================================================================== --- pypy/branch/oo-jit/pypy/translator/test/test_driver.py (original) +++ pypy/branch/oo-jit/pypy/translator/test/test_driver.py Sat May 3 15:46:09 2008 @@ -7,7 +7,7 @@ td = TranslationDriver() expected = ['annotate', 'backendopt', 'llinterpret', 'rtype', 'source', 'compile', 'run', 'prehannotatebackendopt', 'hintannotate', - 'timeshift'] + 'rainbow'] assert set(td.exposed) == set(expected) assert td.backend_select_goals(['compile_c']) == ['compile_c'] @@ -38,7 +38,8 @@ 'run_llvm', 'run_c', 'run_js', 'run_cli', 'compile_jvm', 'source_jvm', 'run_jvm', 'prehannotatebackendopt_lltype', 'hintannotate_lltype', - 'timeshift_lltype'] + 'prehannotatebackendopt_ootype', 'hintannotate_ootype', + 'rainbow_lltype', 'rainbow_ootype'] assert set(td.exposed) == set(expected) td = TranslationDriver({'backend': None, 'type_system': 'lltype'}) @@ -53,6 +54,6 @@ expected = ['annotate', 'backendopt', 'llinterpret', 'rtype', 'source_c', 'source_llvm', 'compile_c', 'compile_llvm', 'run_llvm', - 'run_c', 'prehannotatebackendopt', 'hintannotate', 'timeshift'] + 'run_c', 'prehannotatebackendopt', 'hintannotate', 'rainbow'] assert set(td.exposed) == set(expected) From antocuni at codespeak.net Sat May 3 15:49:49 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Sat, 3 May 2008 15:49:49 +0200 (CEST) Subject: [pypy-svn] r54367 - in pypy/branch/oo-jit/pypy: jit/codegen/cli translator/cli Message-ID: <20080503134949.5D66B2A00E0@codespeak.net> Author: antocuni Date: Sat May 3 15:49:48 2008 New Revision: 54367 Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py pypy/branch/oo-jit/pypy/translator/cli/cts.py pypy/branch/oo-jit/pypy/translator/cli/ilgenerator.py pypy/branch/oo-jit/pypy/translator/cli/opcodes.py Log: - store ObjectConst.value as ootype.Object instead of the CLI System.Object - add support for char const - add support for void return values - remove some old code referencing llmemory.Address, which should never be seen here Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py (original) +++ pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py Sat May 3 15:49:48 2008 @@ -1,13 +1,11 @@ from pypy.tool.pairtype import extendabletype from pypy.rpython.ootypesystem import ootype -from pypy.rpython.lltypesystem import lltype, llmemory from pypy.rlib.objectmodel import specialize from pypy.jit.codegen.model import AbstractRGenOp, GenBuilder, GenLabel from pypy.jit.codegen.model import GenVarOrConst, GenVar, GenConst, CodeGenSwitch from pypy.jit.codegen.cli import operation as ops from pypy.jit.codegen.cli.dumpgenerator import DumpGenerator from pypy.translator.cli.dotnet import CLR, typeof, new_array, box, unbox, clidowncast, classof -from pypy.translator.cli.dotnet import cast_record_to_object, cast_object_to_record System = CLR.System Utils = CLR.pypy.runtime.Utils DelegateHolder = CLR.pypy.runtime.DelegateHolder @@ -16,10 +14,13 @@ DUMP_IL = False DEBUG = False +cVoid = ootype.nullruntimeclass cInt32 = classof(System.Int32) cBoolean = classof(System.Boolean) cDouble = classof(System.Double) cObject = classof(System.Object) +cString = classof(System.String) +cChar = classof(System.Char) class SigToken: def __init__(self, args, res, funcclass): @@ -29,7 +30,10 @@ def class2type(cls): 'Cast a PBC of type ootype.Class into a System.Type instance' - return clidowncast(box(cls), System.Type) + if cls is cVoid: + return None + else: + return clidowncast(box(cls), System.Type) class __extend__(GenVarOrConst): __metaclass__ = extendabletype @@ -85,8 +89,9 @@ class IntConst(GenConst): - def __init__(self, value): + def __init__(self, value, clitype): self.value = value + self.clitype = clitype @specialize.arg(1) def revealconst(self, T): @@ -94,17 +99,19 @@ return self.value elif T is ootype.Bool: return bool(self.value) + elif T is ootype.Char: + return chr(self.value) else: assert False def getCliType(self): - return typeof(System.Int32) + return self.clitype def load(self, builder): builder.il.Emit(OpCodes.Ldc_I4, self.value) def __repr__(self): - return "const=%s" % self.value + return "int const=%s" % self.value class FloatConst(GenConst): @@ -115,8 +122,7 @@ @specialize.arg(1) def revealconst(self, T): assert T is ootype.Float - if T is ootype.Float: - return self.value + return self.value def getCliType(self): return typeof(System.Double) @@ -125,7 +131,7 @@ builder.il.Emit(OpCodes.Ldc_R8, self.value) def __repr__(self): - return "const=%s" % self.value + return "float const=%s" % self.value class BaseConst(GenConst): @@ -165,13 +171,7 @@ @specialize.arg(1) def revealconst(self, T): - if T is llmemory.Address: - return unbox(self.obj, ootype.ROOT) # XXX - elif isinstance(T, ootype.Record): - return cast_object_to_record(T, self.obj) - else: - assert isinstance(T, ootype.OOType) - return unbox(self.obj, T) + return ootype.cast_from_object(T, self.obj) OBJECT = System.Object._INSTANCE @@ -217,19 +217,15 @@ def genconst(self, llvalue): T = ootype.typeOf(llvalue) if T is ootype.Signed: - return IntConst(llvalue) + return IntConst(llvalue, typeof(System.Int32)) elif T is ootype.Bool: - return IntConst(int(llvalue)) + return IntConst(int(llvalue), typeof(System.Boolean)) + elif T is ootype.Char: + return IntConst(ord(llvalue), typeof(System.Char)) elif T is ootype.Float: return FloatConst(llvalue) - elif T is llmemory.Address: - assert llvalue is llmemory.NULL - return zero_const - elif isinstance(T, ootype.Record): - obj = cast_record_to_object(llvalue) - return ObjectConst(obj) elif isinstance(T, ootype.OOType): - obj = box(llvalue) + obj = ootype.cast_to_object(llvalue) return ObjectConst(obj) else: assert False, "XXX not implemented" @@ -237,7 +233,7 @@ @staticmethod def genzeroconst(kind): if kind is cInt32: - return IntConst(0) + return IntConst(0, typeof(System.Int32)) else: return zero_const # ??? @@ -245,8 +241,6 @@ @specialize.memo() def sigToken(FUNCTYPE): """Return a token describing the signature of FUNCTYPE.""" - # XXX: the right thing to do would be to have a way to - # represent typeof(t) as a pbc args = [RCliGenOp.kindToken(T) for T in FUNCTYPE.ARGS] res = RCliGenOp.kindToken(FUNCTYPE.RESULT) funcclass = classof(FUNCTYPE) @@ -256,13 +250,17 @@ @specialize.memo() def kindToken(T): if T is ootype.Void: - return None + return cVoid elif T is ootype.Signed: return cInt32 elif T is ootype.Bool: return cBoolean elif T is ootype.Float: return cDouble + elif T is ootype.String: + return cString + elif T is ootype.Char: + return cChar elif isinstance(T, ootype.Instance): return cObject # XXX? else: @@ -469,5 +467,4 @@ global_rgenop = RCliGenOp() RCliGenOp.constPrebuiltGlobal = global_rgenop.genconst -NULL = ootype.null(System.Object._INSTANCE) -zero_const = ObjectConst(NULL) +zero_const = ObjectConst(ootype.NULL) Modified: pypy/branch/oo-jit/pypy/translator/cli/cts.py ============================================================================== --- pypy/branch/oo-jit/pypy/translator/cli/cts.py (original) +++ pypy/branch/oo-jit/pypy/translator/cli/cts.py Sat May 3 15:49:48 2008 @@ -147,6 +147,7 @@ ootype.Unicode: types.string, ootype.UnicodeBuilder: types.string_builder, ootype.WeakReference: types.weakref, + ootype.Object: types.object, # maps generic types to their ordinal ootype.List.SELFTYPE_T: types.list, Modified: pypy/branch/oo-jit/pypy/translator/cli/ilgenerator.py ============================================================================== --- pypy/branch/oo-jit/pypy/translator/cli/ilgenerator.py (original) +++ pypy/branch/oo-jit/pypy/translator/cli/ilgenerator.py Sat May 3 15:49:48 2008 @@ -418,6 +418,9 @@ def dup(self, TYPE): self.ilasm.opcode('dup') + def push_null(self, TYPE): + self.ilasm.opcode('ldnull') + def oonewarray(self, TYPE, length): if TYPE.ITEM is ootype.Void: self.new(TYPE) Modified: pypy/branch/oo-jit/pypy/translator/cli/opcodes.py ============================================================================== --- pypy/branch/oo-jit/pypy/translator/cli/opcodes.py (original) +++ pypy/branch/oo-jit/pypy/translator/cli/opcodes.py Sat May 3 15:49:48 2008 @@ -36,6 +36,8 @@ 'oosend': [CallMethod], 'ooupcast': DoNothing, 'oodowncast': [DownCast], + 'cast_to_object': DoNothing, + 'cast_from_object': [DownCast], 'clibox': [Box], 'cliunbox': [Unbox], 'cli_newarray': [NewArray], From cami at codespeak.net Sat May 3 15:58:36 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Sat, 3 May 2008 15:58:36 +0200 (CEST) Subject: [pypy-svn] r54368 - in pypy/branch/gameboy-emulator/pypy/lang/gameboy: . test test/rom Message-ID: <20080503135836.376E52A01A0@codespeak.net> Author: cami Date: Sat May 3 15:58:35 2008 New Revision: 54368 Added: pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/rom/ pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/rom/test_rom1.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/rom/test_rom1.pyc (contents, props changed) Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/constants.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboy.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_gameboy.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/video.py Log: added first rom test fixed bugs in sound fixed some bugs in the drivers Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py Sat May 3 15:58:35 2008 @@ -131,7 +131,9 @@ class Cartridge(object): - + """ + File mapping. Holds the file contents + """ def __init__(self, file=None): self.reset() if file != None: Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/constants.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/constants.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/constants.py Sat May 3 15:58:35 2008 @@ -7,6 +7,8 @@ REGISTERED_BITMAP = [ 0x3C, 0x42, 0xB9, 0xA5, 0xB9, 0xA5, 0x42, 0x3C ] +GAMEBOY_SCREEN_WIDTH = 160 +GAMEBOY_SCREEN_HEIGHT = 144 #___________________________________________________________________________ # CATRIGE TYPES # ___________________________________________________________________________ @@ -229,6 +231,8 @@ AUD3WAVERAM = 0xFF30 BUFFER_LOG_SIZE = 5; + + # ___________________________________________________________________________ # TIMER # ___________________________________________________________________________ Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboy.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboy.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboy.py Sat May 3 15:58:35 2008 @@ -5,32 +5,33 @@ """ from pypy.lang.gameboy import constants -from pyp.lang.gameboy.cpu import * -from pyp.lang.gameboy.cartridge import * -from pyp.lang.gameboy.joypad import * -from pyp.lang.gameboy.ram import * -from pyp.lang.gameboy.serial import * -from pyp.lang.gameboy.sound import * -from pyp.lang.gameboy.video import * -from pyp.lang.gameboy.cartridge import * +from pypy.lang.gameboy.cpu import * +from pypy.lang.gameboy.cartridge import * +from pypy.lang.gameboy.interrupt import * +from pypy.lang.gameboy.joypad import * +from pypy.lang.gameboy.ram import * +from pypy.lang.gameboy.serial import * +from pypy.lang.gameboy.sound import * +from pypy.lang.gameboy.timer import * +from pypy.lang.gameboy.video import * +from pypy.lang.gameboy.cartridge import * class GameBoy(object): def __init__(self): - sel.createDriver() - self.createGamboyPieces() + self.createDrivers() + self.createGamboyElements() def createDrivers(self): - self.createDrivers() self.clock = Clock() + self.joypadDriver = JoypadDriver() self.videoDriver = VideoDriver() self.soundDriver = SoundDriver() - self.joypadDriver = JoypadDriver() - def createGameboyPieces(self): + def createGamboyElements(self): self.ram = RAM() - self.cartridge = Cartridge(storeDriver, self.clock) + self.cartridgeManager = CartridgeManager(self.clock) self.interrupt = Interrupt() self.cpu = CPU(self.interrupt, self) self.serial = Serial(self.interrupt) @@ -39,8 +40,11 @@ self.video = Video(self.videoDriver, self.interrupt, self) self.sound = Sound(self.soundDriver) - def getCartridge(self): - return self.cartridge + def getCartridgeManager(self): + return self.cartridgeManager + + def loadCartridge(self, cartridge): + self.cartridgeManager.load(cartridge) def getFrameSkip(self): return self.video.getFrameSkip() Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py Sat May 3 15:58:35 2008 @@ -12,8 +12,9 @@ audioLength = 0 audioFrequency = 0 - def __init__(self): - + def __init__(self, sampleRate, frequencyTable): + self.sampleRate = sampleRate + self.frequencyTable = frequencyTable self.audioLength=0 self.audioEnvelope=0 self.audioFrequency=0 @@ -26,10 +27,10 @@ self.audioIndex = 0 self.audioLength = 0 self.audioFrequency = 0 + self.enabled = False def reset(self): self.audioIndex = 0 - def getAudioLength(self): return self.audioLength @@ -50,13 +51,15 @@ #SquareWaveGenerator class Channel1(Channel): # Audio Channel 1 int - audioSweep=0 - audio1Index=0 - audio1Length=0 - audioVolume=0 - audio1EnvelopeLength=0 - audioSweepLength=0 - audio1Frequency=0 + def __init__(self, sampleRate, frequencyTable): + Channel.__init__(self, sampleRate, frequencyTable) + self.audioSweep=0 + self.audio1Index=0 + self.audio1Length=0 + self.audioVolume=0 + self.audio1EnvelopeLength=0 + self.audioSweepLength=0 + self.audio1Frequency=0 # Audio Channel 1 def getAudioSweep(self): @@ -72,11 +75,11 @@ def setAudioEnvelope(self, data): self.audioEnvelope = data - if ((self.audioPlayback & 0x40) != 0): + if (self.audioPlayback & 0x40) != 0: return - if ((self.audioEnvelope >> 4) == 0): + if (self.audioEnvelope >> 4) == 0: self.audioVolume = 0 - elif (self.audio1EnvelopeLength == 0 and (self.audioEnvelope & 0x07) == 0): + elif self.audio1EnvelopeLength == 0 and (self.audioEnvelope & 0x07) == 0: self.audioVolume = (self.audioVolume + 1) & 0x0F else: self.audioVolume = (self.audioVolume + 2) & 0x0F @@ -89,9 +92,9 @@ self.audioPlayback = data self.audio1Frequency = self.frequencyTable[self.audioFrequency + ((self.audioPlayback & 0x07) << 8)] - if ((self.audioPlayback & 0x80) != 0): - self.outputEnable |= 0x01 - if ((self.audioPlayback & 0x40) != 0 and self.audio1Length == 0): + if (self.audioPlayback & 0x80) != 0: + self.enabled = True + if (self.audioPlayback & 0x40) != 0 and self.audio1Length == 0: self.audio1Length = (constants.SOUND_CLOCK / 256) * (64 - (self.audioLength & 0x3F)) self.audioSweepLength = (constants.SOUND_CLOCK / 128) * ((self.audioSweep >> 4) & 0x07) self.audioVolume = self.audioEnvelope >> 4 @@ -101,38 +104,36 @@ if (self.audioPlayback & 0x40) != 0 and self.audio1Length > 0: self.audio1Length-=1 if self.audio1Length <= 0: - self.outputEnable &= ~0x01 + self.enabled = False if self.audio1EnvelopeLength > 0: self.audio1EnvelopeLength-=1 - if (self.audio1EnvelopeLength <= 0): - if ((self.audioEnvelope & 0x08) != 0): + if self.audio1EnvelopeLength <= 0: + if (self.audioEnvelope & 0x08) != 0: if (self.audioVolume < 15): self.audioVolume+=1 - elif (self.audioVolume > 0): + elif self.audioVolume > 0: self.audioVolume-=1 self.audio1EnvelopeLength += (constants.SOUND_CLOCK / 64) * (self.audioEnvelope & 0x07) - if (self.audioSweepLength > 0): + if self.audioSweepLength > 0: self.audioSweepLength-=1 - if (self.audioSweepLength <= 0): + if self.audioSweepLength <= 0: sweepSteps = (self.audioSweep & 0x07) - if (sweepSteps != 0): + if sweepSteps != 0: frequency = ((self.audioPlayback & 0x07) << 8) + self.audioFrequency - if ((self.audioSweep & 0x08) != 0): + if (self.audioSweep & 0x08) != 0: frequency -= frequency >> sweepSteps else: frequency += frequency >> sweepSteps - if (frequency < 2048): + if frequency < 2048: self.audio1Frequency = self.frequencyTable[frequency] self.audioFrequency = frequency & 0xFF self.audioPlayback = (self.audioPlayback & 0xF8) + ((frequency >> 8) & 0x07) else: self.audio1Frequency = 0 self.outputEnable &= ~0x01 - self.audioSweepLength += (constants.SOUND_CLOCK / 128) * ((self.audioSweep >> 4) & 0x07) def mixAudio(self, buffer, length): - wavePattern = 0x18 if (self.audioLength & 0xC0) == 0x00: wavePattern = 0x04 @@ -143,41 +144,41 @@ wavePattern << 22 for index in range(0, length, 3): self.audio1Index += self.audio1Frequency - if ((self.audio1Index & (0x1F << 22)) >= wavePattern): - if ((self.outputTerminal & 0x10) != 0): + if (self.audio1Index & (0x1F << 22)) >= wavePattern: + if (self.outputTerminal & 0x10) != 0: buffer[index + 0] -= self.audioVolume - if ((self.outputTerminal & 0x01) != 0): + if (self.outputTerminal & 0x01) != 0: buffer[index + 1] -= self.audioVolume else: - if ((self.outputTerminal & 0x10) != 0): + if (self.outputTerminal & 0x10) != 0: buffer[index + 0] += self.audioVolume - if ((self.outputTerminal & 0x01) != 0): + if (self.outputTerminal & 0x01) != 0: buffer[index + 1] += self.audioVolume #SquareWaveGenerator class Channel2(Channel): - # Audio Channel 2 int - audio2Index=0 - audio2Length=0 - audioVolume=0 - audio2EnvelopeLength=0 - audio2Frequency=0 - - - # Audio Channel 2 + def __init__(self, sampleRate, frequencyTable): + Channel.__init__(self, sampleRate, frequencyTable) + self.audio2Index=0 + self.audio2Length=0 + self.audioVolume=0 + self.audio2EnvelopeLength=0 + self.audio2Frequency=0 + + # Audio Channel 2 def setAudioLength(self, data): self.audioLength = data self.audio2Length = (constants.SOUND_CLOCK / 256) * (64 - (self.audioLength & 0x3F)) def setAudioEnvelope(self, data): self.audioEnvelope = data - if ((self.audioPlayback & 0x40) == 0): - if ((self.audioEnvelope >> 4) == 0): + if (self.audioPlayback & 0x40) == 0: + if (self.audioEnvelope >> 4) == 0: self.audioVolume = 0 - elif (self.audio2EnvelopeLength == 0 and (self.audioEnvelope & 0x07) == 0): + elif self.audio2EnvelopeLength == 0 and (self.audioEnvelope & 0x07) == 0: self.audioVolume = (self.audioVolume + 1) & 0x0F else: self.audioVolume = (self.audioVolume + 2) & 0x0F @@ -191,26 +192,26 @@ self.audioPlayback = data self.audio2Frequency = self.frequencyTable[self.audioFrequency\ + ((self.audioPlayback & 0x07) << 8)] - if ((self.audioPlayback & 0x80) != 0): - self.outputEnable |= 0x02 - if ((self.audioPlayback & 0x40) != 0 and self.audio2Length == 0): + if (self.audioPlayback & 0x80) != 0: + self.enabled = True + if (self.audioPlayback & 0x40) != 0 and self.audio2Length == 0: self.audio2Length = (constants.SOUND_CLOCK / 256) * (64 - (self.audioLength & 0x3F)) self.audioVolume = self.audioEnvelope >> 4 self.audio2EnvelopeLength = (constants.SOUND_CLOCK / 64) * (self.audioEnvelope & 0x07) def updateAudio(self): - if ((self.audioPlayback & 0x40) != 0 and self.audio2Length > 0): + if (self.audioPlayback & 0x40) != 0 and self.audio2Length > 0: self.audio2Length-=1 - if (self.audio2Length <= 0): - self.outputEnable &= ~0x02 - if (self.audio2EnvelopeLength > 0): + if self.audio2Length <= 0: + self.enabled = False + if self.audio2EnvelopeLength > 0: self.audio2EnvelopeLength-=1 - if (self.audio2EnvelopeLength <= 0): - if ((self.audioEnvelope & 0x08) != 0): - if (self.audioVolume < 15): + if self.audio2EnvelopeLength <= 0: + if (self.audioEnvelope & 0x08) != 0: + if self.audioVolume < 15: self.audioVolume+=1 - elif (self.audioVolume > 0): + elif self.audioVolume > 0: self.audioVolume-=1 self.audio2EnvelopeLength += (constants.SOUND_CLOCK / 64) * (self.audioEnvelope & 0x07) @@ -242,13 +243,15 @@ #SquareWaveGenerator class Channel3(Channel): - # Audio Channel 3 int - audioEnable=0 - audioLevel=0 - audio3Index=0 - audio3Length=0 - audio3Frequency=0 - audio3WavePattern = []# = new byte[16] + # Audio Channel 3 int + def __init__(self, sampleRate, frequencyTable): + Channel.__init__(self, sampleRate, frequencyTable) + self.audioEnable=0 + self.audioLevel=0 + self.audio3Index=0 + self.audio3Length=0 + self.audio3Frequency=0 + self.audioWavePattern = [0]*16 # Audio Channel 3 @@ -264,8 +267,8 @@ def setAudioEnable(self, data): self.audioEnable = data & 0x80 - if ((self.audioEnable & 0x80) == 0): - self.outputEnable &= ~0x04 + if (self.audioEnable & 0x80) == 0: + self.enabled = False def setAudioLength(self, data): self.audioLength = data @@ -281,21 +284,21 @@ def setAudioPlayback(self, data): self.audioPlayback = data self.audio3Frequency = self.frequencyTable[((self.audioPlayback & 0x07) << 8) + self.audioFrequency] >> 1 - if ((self.audioPlayback & 0x80) != 0 and (self.audioEnable & 0x80) != 0): - self.outputEnable |= 0x04 - if ((self.audioPlayback & 0x40) != 0 and self.audio3Length == 0): + if (self.audioPlayback & 0x80) != 0 and (self.audioEnable & 0x80) != 0: + self.enabled = True + if (self.audioPlayback & 0x40) != 0 and self.audio3Length == 0: self.audio3Length = (constants.SOUND_CLOCK / 256) * (256 - self.audioLength) def setAudioWavePattern(self, address, data): - self.audio3WavePattern[address & 0x0F] = data + self.audioWavePattern[address & 0x0F] = data def getAudioWavePattern(self, address): - return self.audio3WavePattern[address & 0x0F] & 0xFF + return self.audioWavePattern[address & 0x0F] & 0xFF def updateAudio(self): - if ((self.audioPlayback & 0x40) != 0 and self.audio3Length > 0): + if (self.audioPlayback & 0x40) != 0 and self.audio3Length > 0: self.audio3Length-=1 - if (self.audio3Length <= 0): + if self.audio3Length <= 0: self.outputEnable &= ~0x04 def mixAudio(self, buffer, length): @@ -308,7 +311,7 @@ wavePattern = 1 for index in range(0, length, 2): self.audio3Index += self.audio3Frequency - sample = self.audio3WavePattern[(self.audio3Index >> 23) & 0x0F] + sample = self.audioWavePattern[(self.audio3Index >> 23) & 0x0F] if ((self.audio3Index & (1 << 22)) != 0): sample = (sample >> 0) & 0x0F else: @@ -324,45 +327,43 @@ class NoiseGenerator(Channel): - # Audio Channel 4 int - audioLength=0 - audioPolynomial=0 - audio4Index=0 - audio4Length=0 - audioVolume=0 - audio4EnvelopeLength=0 - audio4Frequency=0 - - # Frequency Table - frequencyTable = [0]*2048#= new int[2048] - noiseFreqRatioTable = [0]*8 #= new int[8] - - # Noise Tables - noiseStep7Table = [0]*4 #= new int[128 / 32] - noiseStep15Table = [0]*1024 #= new int[32768 / 32] - - #Frequency Table Generation - def generateFrequencyTables(self): - sampleRate = self.driver.getSampleRate() - # frequency = (4194304 / 32) / (2048 - period) Hz - for period in range(0, 2048): - skip = (((constants.GAMEBOY_CLOCK << 10) / sampleRate) << 16) / (2048 - period) - if skip >= (32 << 22): - self.frequencyTable[period] = 0 - else: - self.frequencyTable[period] = skip + + def __init__(self, sampleRate, frequencyTable): + Channel.__init__(self, sampleRate, frequencyTable) + # Audio Channel 4 int + self.audioLength=0 + self.audioPolynomial=0 + self.audio4Index=0 + self.audio4Length=0 + self.audioVolume=0 + self.audio4EnvelopeLength=0 + self.audio4Frequency=0 + + self.generateNoiseFrequencyRatioTable() + self.generateNoiseTables() + + + def generateNoiseFrequencyRatioTable(self): + self.noiseFreqRatioTable = [0] * 8 # Polynomial Noise Frequency Ratios # 4194304 Hz * 1/2^3 * 2 4194304 Hz * 1/2^3 * 1 4194304 Hz * 1/2^3 * # 1/2 4194304 Hz * 1/2^3 * 1/3 4194304 Hz * 1/2^3 * 1/4 4194304 Hz * # 1/2^3 * 1/5 4194304 Hz * 1/2^3 * 1/6 4194304 Hz * 1/2^3 * 1/7 + sampleFactor = ((1 << 16) / self.sampleRate) for ratio in range(0, 8): divider = 1 if ratio != 0: divider = 2 * ratio - self.noiseFreqRatioTable[ratio] = (constants.GAMEBOY_CLOCK / divider) * ((1 << 16) / sampleRate) - + self.noiseFreqRatioTable[ratio] = (constants.GAMEBOY_CLOCK / divider) *sampleFactor + # Noise Generation def generateNoiseTables(self): + self.create7StepNoiseTable() + self.create15StepNoiseTable() + + def create7StepNoiseTable(self): + # Noise Tables + self. noiseStep7Table = [0]*4 #= new int[128 / 32] polynomial = 0x7F # 7 steps for index in range(0, 0x7F): @@ -370,7 +371,11 @@ if (index & 31) == 0: self.noiseStep7Table[index >> 5] = 0 self.noiseStep7Table[index >> 5] |= (polynomial & 1) << (index & 31) + + def create15StepNoiseTable(self): # 15 steps& + + self.noiseStep15Table = [0]*1024 #= new int[32768 / 32] polynomial = 0x7FFF for index in range(0, 0x7FFF): polynomial = (((polynomial << 14) ^ (polynomial << 13)) & 0x4000) | (polynomial >> 1) @@ -412,7 +417,7 @@ def setAudioPlayback(self, data): self.audioPlayback = data if (self.audioPlayback & 0x80) != 0: - self.outputEnable |= 0x08 + self.enabled = True if (self.audioPlayback & 0x40) != 0 and self.audio4Length == 0: self.audio4Length = (constants.SOUND_CLOCK / 256) * (64 - (self.audioLength & 0x3F)) self.audioVolume = self.audioEnvelope >> 4 @@ -459,20 +464,6 @@ - -# ------------------------------------------------------------------------------ - - -class VoluntaryWaveGenerator(Channel): - - def __init__(self): - Channel.__init__(self) - self.createWavePatterns() - - def createWavePatterns(self): - self.audioWavePattern = [0]*16 - - # ------------------------------------------------------------------------------ @@ -485,18 +476,29 @@ self.outputEnable=0 self.driver = soundDriver + self.sampleRate = self.driver.getSampleRate() + + self.generateFrequencyTable() self.createAudioChannels() - self.generateFrequencyTables() - self.generateNoiseTables() self.reset() def createAudioChannels(self): - self.channel1 = SquareWaveGenerator(self.sampleRate) - self.channel2 = SquareWaveGenerator(self.sampleRate) - self.channel3 = VoluntaryWaveGenerator(self.sampleRate) - self.channel4 = NoiseGenerator(self.sampleRate) + self.channel1 = Channel1(self.sampleRate, self.frequencyTable) + self.channel2 = Channel2(self.sampleRate, self.frequencyTable) + self.channel3 = Channel3(self.sampleRate, self.frequencyTable) + self.channel4 = NoiseGenerator(self.sampleRate, self.frequencyTable) + + def generateFrequencyTable(self): + self.frequencyTable = [0] * 2048 + # frequency = (4194304 / 32) / (2048 - period) Hz + for period in range(0, 2048): + skip = (((constants.GAMEBOY_CLOCK << 10) / self.sampleRate) << 16) / (2048 - period) + if skip >= (32 << 22): + self.frequencyTable[period] = 0 + else: + self.frequencyTable[period] = skip def reset(self): self.cycles = constants.GAMEBOY_CLOCK / constants.SOUND_CLOCK @@ -533,9 +535,9 @@ self.write(constants.NR43, 0x00) self.write(constants.NR44, 0xBF) - self.write(constants.outputLevel, 0x00) # 0x77 - self.write(constants.outputTerminal, 0xF0) - self.write(constants.outputEnable, 0xFF) # 0xF0 + self.write(constants.NR50, 0x00) # 0x77 + self.write(constants.NR51, 0xF0) + self.write(constants.NR52, 0xFF) # 0xF0 for address in range(0xFF30, 0xFF3F): write = 0xFF @@ -558,7 +560,6 @@ self.updateAudio() if self.driver.isEnabled(): self.mixDownAudio() - self.cycles += constants.GAMEBOY_CLOCK / constants.SOUND_CLOCK def mixDownAudio(self): @@ -609,11 +610,11 @@ elif address==constants.NR44: return self.channel4.getAudioPlayback() - elif address==constants.outputLevel: + elif address==constants.NR50: return self.getOutputLevel() - elif address==constants.outputTerminal: + elif address==constants.NR51: return self.getOutputTerminal() - elif address==constants.outputEnable: + elif address==constants.NR52: return self.getOutputEnable() elif (address >= constants.AUD3WAVERAM and address <= constants.AUD3WAVERAM + 0x3F): @@ -628,7 +629,7 @@ elif address == constants.NR12: self.channel1.setAudioEnvelope(data) elif address == constants.NR13: - self.channel1.setAudi1Frequency(data) + self.channel1.setAudioFrequency(data) elif address == constants.NR14: self.channel1.setAudioPlayback(data) @@ -661,11 +662,11 @@ elif address == constants.NR44: self.channel4.setAudioPlayback(data) - elif address == constants.outputLevel: + elif address == constants.NR50: self.setOutputLevel(data) - elif address == constants.outputTerminal: + elif address == constants.NR51: self.setOutputTerminal(data) - elif address == constants.outputEnable: + elif address == constants.NR52: self.setOutputEnable(data) elif (address >= constants.AUD3WAVERAM and address <= constants.AUD3WAVERAM + 0x3F): @@ -726,12 +727,15 @@ def __init__(self): self.enabled = True + self.sampleRate = 44100 + self.channelCount = 2 + self.bitsPerSample = 8 def isEnabled(self): return self.enabled def getSampleRate(self): - self.sampleRate + return self.sampleRate def getChannels(self): return self.channelCount Added: pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/rom/test_rom1.py ============================================================================== --- (empty file) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/rom/test_rom1.py Sat May 3 15:58:35 2008 @@ -0,0 +1,15 @@ + +import py +from pypy.lang.gameboy import constants +from pypy.lang.gameboy.cpu import * +from pypy.lang.gameboy.cartridge import * +from pypy.lang.gameboy.gameboy import * + + +ROM_PATH = str(py.magic.autopath().dirpath().dirpath())+"/rom" + + + +def test_rom1(): + gameBoy = GameBoy() + \ No newline at end of file Added: pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/rom/test_rom1.pyc ============================================================================== Binary file. No diff available. Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_gameboy.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_gameboy.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_gameboy.py Sat May 3 15:58:35 2008 @@ -0,0 +1,14 @@ + +import py +from pypy.lang.gameboy.gameboy import * + + + +def get_gameboy(): + gameboy = GameBoy() + return gameboy + + + +def test_init(): + gameboy = get_gameboy() \ No newline at end of file Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/video.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/video.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/video.py Sat May 3 15:58:35 2008 @@ -5,6 +5,7 @@ from pypy.lang.gameboy import constants + class Video(object): #frames = 0 #frameSkip = 0 @@ -15,7 +16,7 @@ #palette = []#= new int[1024] - def __init__(self, videDriver, interrupt, memory): + def __init__(self, videoDriver, interrupt, memory): self.driver = videoDriver self.interrupt = interrupt self.memory = memory @@ -148,7 +149,6 @@ else: self.emulateTransfer() - def getControl(self): return self.control @@ -574,12 +574,12 @@ class VideoDriver(object): - def __init__(self, width, height): - self.width = width - self.height = height + def __init__(self): + self.width = constants.GAMEBOY_SCREEN_WIDTH + self.height = constants.GAMEBOY_SCREEN_HEIGHT self.clearPixels() - def clearPixels(): + def clearPixels(self): self.pixels = [0] * self.width * self.height def getWidth(self): @@ -593,5 +593,4 @@ def updateDisplay(self): self.resetPixels() - \ No newline at end of file From antocuni at codespeak.net Sat May 3 16:18:19 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Sat, 3 May 2008 16:18:19 +0200 (CEST) Subject: [pypy-svn] r54369 - in pypy/branch/oo-jit/pypy/jit/codegen: cli/test ia32/test Message-ID: <20080503141819.095E12A01A0@codespeak.net> Author: antocuni Date: Sat May 3 16:18:19 2008 New Revision: 54369 Added: pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_gencli_portal.py (contents, props changed) Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_gencli_ts.py pypy/branch/oo-jit/pypy/jit/codegen/ia32/test/test_genc_portal.py Log: port test_portal to gencli; no test works so far Added: pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_gencli_portal.py ============================================================================== --- (empty file) +++ pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_gencli_portal.py Sat May 3 16:18:19 2008 @@ -0,0 +1,39 @@ +import py +from pypy.tool.udir import udir +from pypy.translator.cli.entrypoint import StandaloneEntryPoint +from pypy.translator.cli.gencli import GenCli +from pypy.translator.cli.sdk import SDK +from pypy.jit.codegen.ia32.test.test_genc_portal import I386PortalTestMixin +from pypy.jit.rainbow.test import test_portal +from pypy.jit.codegen.cli.rgenop import RCliGenOp + +class CliPortalTestMixin(I386PortalTestMixin): + RGenOp = RCliGenOp + + def getgraph(self, fn): + bk = self.rtyper.annotator.bookkeeper + return bk.getdesc(fn).getuniquegraph() + + def compile(self, ll_main): + graph = self.getgraph(ll_main) + entrypoint = StandaloneEntryPoint(graph) + gen = GenCli(udir, self.rtyper.annotator.translator, entrypoint) + gen.generate_source() + self.executable_name = gen.build_exe() + + def cmdexec(self, args=''): + assert self.executable_name + mono = ''.join(SDK.runtime()) + return py.process.cmdexec('%s "%s" %s' % (mono, self.executable_name, args)) + + +class TestPortal(CliPortalTestMixin, + test_portal.TestPortalOOType): + + # for the individual tests see + # ====> ../../../rainbow/test/test_portal.py + + def skip(self): + py.test.skip('in progress') + + test_cast_ptr_to_int = skip Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_gencli_ts.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_gencli_ts.py (original) +++ pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_gencli_ts.py Sat May 3 16:18:19 2008 @@ -1,4 +1,5 @@ import py +py.test.skip('port me') from pypy.tool.udir import udir from pypy.translator.cli.entrypoint import StandaloneEntryPoint from pypy.translator.cli.gencli import GenCli Modified: pypy/branch/oo-jit/pypy/jit/codegen/ia32/test/test_genc_portal.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/codegen/ia32/test/test_genc_portal.py (original) +++ pypy/branch/oo-jit/pypy/jit/codegen/ia32/test/test_genc_portal.py Sat May 3 16:18:19 2008 @@ -22,7 +22,7 @@ # ---------- run the stand-alone executable ---------- cmdargs = ' '.join([str(arg) for arg in main_args]) - output = self.cbuilder.cmdexec(cmdargs) + output = self.cmdexec(cmdargs) lines = output.split() lastline = lines[-1] assert not lastline.startswith('EXCEPTION:') @@ -78,19 +78,26 @@ backendoptimize=backendoptimize) # ---------- generate a stand-alone executable ---------- - t = self.rtyper.annotator.translator - t.config.translation.gc = 'boehm' - self.cbuilder = CStandaloneBuilder(t, ll_main, config=t.config) - self.cbuilder.generate_source() - exename = self.cbuilder.compile() + exename = self.compile(ll_main) print '-'*60 print 'Generated executable for %s: %s' % (self.testname, exename) print '-'*60 - def check_insns(self, expected=None, **counts): "Cannot check instructions in the generated assembler." + def compile(self, ll_main): + t = self.rtyper.annotator.translator + t.config.translation.gc = 'boehm' + cbuilder = CStandaloneBuilder(t, ll_main, config=t.config) + cbuilder.generate_source() + exename = cbuilder.compile() + self.main_cbuilder= cbuilder + return exename + + def cmdexec(self, args): + return self.main_cbuilder.cmdexec(args) + class TestPortal(I386PortalTestMixin, test_portal.TestPortalLLType): From antocuni at codespeak.net Sat May 3 16:26:52 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Sat, 3 May 2008 16:26:52 +0200 (CEST) Subject: [pypy-svn] r54370 - pypy/branch/oo-jit/pypy/jit/codegen/cli Message-ID: <20080503142652.EBBD12A0151@codespeak.net> Author: antocuni Date: Sat May 3 16:26:52 2008 New Revision: 54370 Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py Log: store the cliclass instead of the clitype on IntConst Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py (original) +++ pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py Sat May 3 16:26:52 2008 @@ -89,9 +89,9 @@ class IntConst(GenConst): - def __init__(self, value, clitype): + def __init__(self, value, cliclass): self.value = value - self.clitype = clitype + self.cliclass = cliclass @specialize.arg(1) def revealconst(self, T): @@ -105,7 +105,7 @@ assert False def getCliType(self): - return self.clitype + return class2type(self.cliclass) def load(self, builder): builder.il.Emit(OpCodes.Ldc_I4, self.value) @@ -217,11 +217,11 @@ def genconst(self, llvalue): T = ootype.typeOf(llvalue) if T is ootype.Signed: - return IntConst(llvalue, typeof(System.Int32)) + return IntConst(llvalue, cInt32) elif T is ootype.Bool: - return IntConst(int(llvalue), typeof(System.Boolean)) + return IntConst(int(llvalue), cBoolean) elif T is ootype.Char: - return IntConst(ord(llvalue), typeof(System.Char)) + return IntConst(ord(llvalue), cChar) elif T is ootype.Float: return FloatConst(llvalue) elif isinstance(T, ootype.OOType): @@ -233,7 +233,7 @@ @staticmethod def genzeroconst(kind): if kind is cInt32: - return IntConst(0, typeof(System.Int32)) + return IntConst(0, cInt32) else: return zero_const # ??? From antocuni at codespeak.net Sat May 3 16:35:13 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Sat, 3 May 2008 16:35:13 +0200 (CEST) Subject: [pypy-svn] r54371 - pypy/branch/oo-jit/pypy/jit/rainbow/test Message-ID: <20080503143513.1E6FD2A0151@codespeak.net> Author: antocuni Date: Sat May 3 16:35:12 2008 New Revision: 54371 Modified: pypy/branch/oo-jit/pypy/jit/rainbow/test/test_portal.py Log: rename test so that it's easier to select only this with py.test -k Modified: pypy/branch/oo-jit/pypy/jit/rainbow/test/test_portal.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/rainbow/test/test_portal.py (original) +++ pypy/branch/oo-jit/pypy/jit/rainbow/test/test_portal.py Sat May 3 16:35:12 2008 @@ -85,7 +85,7 @@ class BaseTestPortal(PortalTest): type_system = "lltype" - def test_simple(self): + def test_very_simple(self): def main(code, x): return evaluate(code, x) From cami at codespeak.net Sat May 3 16:47:06 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Sat, 3 May 2008 16:47:06 +0200 (CEST) Subject: [pypy-svn] r54372 - in pypy/branch/gameboy-emulator/pypy/lang/gameboy: . test test/rom Message-ID: <20080503144706.291B12A0151@codespeak.net> Author: cami Date: Sat May 3 16:47:04 2008 New Revision: 54372 Added: pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_rom.py Removed: pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/rom/ Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/constants.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboy.py Log: cartridge rom loading test completed fixed some inheritence bugs in CatridrgeMemoryBanks Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py Sat May 3 16:47:04 2008 @@ -54,43 +54,43 @@ self.checkROM() self.createRAM() self.loadBattery() - self.mbc = self.createBankController(self.getMemoryBankType(), rom, ram, clock) + self.mbc = self.createBankController(self.getMemoryBankType(), self.rom, self.ram, self.clock) def checkROM(self): if not self.verifyHeader(): raise Exeption("Cartridge header is corrupted") - if romSize < self.getROMSize(): + if self.cartridge.getSize() < self.getROMSize(): raise Exeption("Cartridge is truncated") def createRAM(self): ramSize = self.getRAMSize() - if (getMemoryBankType() >= constants.TYPE_MBC2 - and getMemoryBankType() <= constants.TYPE_MBC2_BATTERY): + if self.getMemoryBankType() >= constants.TYPE_MBC2 \ + and self.getMemoryBankType() <= constants.TYPE_MBC2_BATTERY: ramSize = 512 self.ram = [0xFF]*ramSize def loadBattery(self): - if self.store.hasBattery(cartridgeName): - self.store.readBattery(cartridgeName, self.ram) + if self.cartridge.hasBattery(): + self.ram = self.cartridge.readBattery() def save(self, cartridgeName): - if self.hasBattery(): - self.store.writeBattery(cartridgeName, self.ram) + if self.cartridge.hasBattery(): + self.cartridge.writeBattery(self.ram) def getMemoryBankType(self): - return self.rom[constants.MEMORY_BANK_MAPPING] & 0xFF + return self.rom[constants.CARTRIDGE_TYPE_ADDRESS] & 0xFF def getRom(self): return self.rom def getROMSize(self): - romSize = self.rom[constants.CARTRIDGE_SIZE_ADDRESS] & 0xFF + romSize = self.rom[constants.CARTRIDGE_ROM_SIZE_ADDRESS] & 0xFF if romSize>=0x00 and romSize<=0x07: return 32768 << romSize return -1 def getRAMSize(self): - return constants.RAM_SIZE_MAPPING[self.rom[constants.RAM_SIZE_ADDRESS]] + return constants.CARTRIDGE_RAM_SIZE_MAPPING[self.rom[constants.CARTRIDGE_RAM_SIZE_ADDRESS]] def getDestinationCode(self): return self.rom[constants.DESTINATION_CODE_ADDRESS] & 0xFF @@ -99,13 +99,14 @@ return self.rom[constants.LICENSEE_ADDRESS] & 0xFF def getROMVersion(self): - return self.rom[constants.ROM_VERSION_ADDRESS] & 0xFF + return self.rom[constants.CARTRIDGE_ROM_VERSION_ADDRESS] & 0xFF def getHeaderChecksum(self): return self.rom[constants.HEADER_CHECKSUM_ADDRESS] & 0xFF def getChecksum(self): - return ((rom[constants.CHECKSUM_A_ADDRESS] & 0xFF) << 8) + (rom[constants.CHECKSUM_B_ADDRESS] & 0xFF) + return ((self.rom[constants.CHECKSUM_A_ADDRESS] & 0xFF) << 8) \ + + (self.rom[constants.CHECKSUM_B_ADDRESS] & 0xFF) def hasBattery(self): return hasCartridgeBattery(self.getMemoryBankType()) @@ -118,11 +119,11 @@ return (checksum == self.getChecksum()) def verifyHeader(self): - if self.rom.length < 0x0150: - return false + if len(self.rom) < 0x0150: + return False checksum = 0xE7 for address in range(0x0134, 0x014C): - checksum = (checksum - (rom[address] & 0xFF)) & 0xFF + checksum = (checksum - (self.rom[address] & 0xFF)) & 0xFF return (checksum == self.getHeaderChecksum()) def createBankController(self, type, rom, ram, clockDriver): @@ -142,8 +143,7 @@ def reset(self): self.cartridgeName ="" self.cartridgeFilePath = "" - self.cartridgeFile = None - + self.cartridgeFile = None self.batteryName ="" self.batteryFilePath = "" self.batteryFile = None @@ -191,6 +191,12 @@ def removeBattery(self): if self.hasBattery(): os.remove(self.batteryFilePath) + + def getSize(self): + return os.path.getsize(self.cartridgeFilePath) + + def getBatterySize(self): + return os.path.getsize(self.batteryFilePath) @@ -221,15 +227,15 @@ def setROM(self, buffer): banks = len(buffer) / constants.ROM_BANK_SIZE - if (banks < minRomBankSize or banks > maxRomBankSize): + if banks < self.minRomBankSize or banks > self.maxRomBankSize: raise Exception("Invalid constants.ROM size") self.rom = buffer self.romSize = constants.ROM_BANK_SIZE*banks - 1 - def setRAM(buffer): + def setRAM(self, buffer): banks = len(buffer) / constants.RAM_BANK_SIZE - if (banks < minRamBankSize or banks > maxRamBankSize): + if banks < self.minRamBankSize or banks > self.maxRamBankSize: raise Exception("Invalid constants.RAM size") self.ram = buffer self.ramSize = constants.RAM_BANK_SIZE*banks - 1 @@ -238,14 +244,32 @@ def read(self, address): if address <= 0x3FFF: # 0000-3FFF return self.rom[address] & 0xFF - elif (address <= 0x7FFF):# 4000-7FFF + elif address <= 0x7FFF:# 4000-7FFF return self.rom[romBank + (address & 0x3FFF)] & 0xFF - elif (address >= 0xA000 and address <= 0xBFFF and self.ramEnable): # A000-BFFF + elif address >= 0xA000 and address <= 0xBFFF and self.ramEnable: # A000-BFFF return self.ram[self.ramBank + (address & 0x1FFF)] & 0xFF return 0xFF def write(self, address, data): pass + + +#------------------------------------------------------------------------------- + + +class DefaultMBC(MBC): + + def __init__(self, rom, ram, clockDriver): + self.reset() + self.minRomBankSize = 0 + self.maxRomBankSize = 0xFFFFFF + self.minRamBankSize = 0 + self.maxRamBankSize = 0xFFFFFF + MBC.__init__(self, rom, ram, clockDriver) + + +#------------------------------------------------------------------------------- + class MBC1(MBC): """ @@ -263,42 +287,46 @@ self.maxRamBankSize = 4 self.minRomBankSize = 2 self.maxRomBankSize = 128 - super.__init__(rom, ram, clockDriver) + MBC.__init__(self, rom, ram, clockDriver) def reset(self): - super.reset() + MBC.reset(self) self.memoryModel = 0 def write(self, address, data): - if (address <= 0x1FFF): # 0000-1FFF + if address <= 0x1FFF: # 0000-1FFF self.writeRAMEnable(address, data) - elif (address <= 0x3FFF): # 2000-3FFF + elif address <= 0x3FFF: # 2000-3FFF self.writeROMBank1(address, data) - elif (address <= 0x5FFF): # 4000-5FFF + elif address <= 0x5FFF: # 4000-5FFF self.writeROMBank2(address, data) - elif (address <= 0x7FFF): # 6000-7FFF + elif address <= 0x7FFF: # 6000-7FFF self.memoryModel = data & 0x01 - elif (address >= 0xA000 and address <= 0xBFFF and self.ramEnable): # A000-BFFF + elif address >= 0xA000 and address <= 0xBFFF and self.ramEnable: # A000-BFFF self.ram[self.ramBank + (address & 0x1FFF)] = data def writeRAMEnable(self, address, data): - if (self.ramSize > 0): + if self.ramSize > 0: self.ramEnable = ((data & 0x0A) == 0x0A) def writeROMBank1(self, address, data): - if ((data & 0x1F) == 0): + if (data & 0x1F) == 0: data = 1 - if (self.memoryModel == 0): + if self.memoryModel == 0: self.romBank = ((self.romBank & 0x180000) + ((data & 0x1F) << 14)) & self.romSize else: self.romBank = ((data & 0x1F) << 14) & self.romSize def writeROMBank2(self, address, data): - if (self.memoryModel == 0): + if self.memoryModel == 0: self.romBank = ((self.romBank & 0x07FFFF) + ((data & 0x03) << 19)) & self.romSize else: self.ramBank = ((data & 0x03) << 13) & self.ramSize - + + +#------------------------------------------------------------------------------- + + class MBC2(MBC): """ PyBoy GameBoy (TM) Emulator @@ -318,7 +346,7 @@ self.maxRamBankSize = constants.RAM_BANK_SIZE self.minRomBankSize = 2 self.maxRomBankSize = 16 - super.__init__(rom, ram, clockDriver) + MBC.__init__(self, rom, ram, clockDriver) def read(self, address): @@ -328,11 +356,11 @@ return super.read(address) def write(self, address, data): - if (address <= 0x1FFF): # 0000-1FFF + if address <= 0x1FFF: # 0000-1FFF self.writeRAMEnable(address, data) - elif (address <= 0x3FFF): # 2000-3FFF + elif address <= 0x3FFF: # 2000-3FFF self.writeROMBank() - elif (address >= 0xA000 and address <= 0xA1FF): # A000-A1FF + elif address >= 0xA000 and address <= 0xA1FF: # A000-A1FF self.writeRAMEnable(address, data) def writeRAMEnable(self, address, data): @@ -348,7 +376,11 @@ def writeRAM(self, address, data): if self.ramEnable: - self.ram[address & 0x01FF] = (byte) (data & 0x0F) + self.ram[address & 0x01FF] = data & 0x0F + + +#------------------------------------------------------------------------------- + class MBC3(MBC): """ @@ -360,7 +392,6 @@ 4000-7FFF ROM Bank 1-127 (16KB) A000-BFFF RAM Bank 0-3 (8KB) """ - def __init__(self, rom, ram, clock): self.reset() self.minRamBankSize = 0 @@ -371,12 +402,12 @@ self.clock = clock self.clockLDaysclockLControl = None - super.__init__(rom, ram, clockDriver) + MBC.__init__(self, rom, ram, clockDriver) self.reset() - def reset(): - super.reset() + def reset(self): + MBC.reset(self) self.clockTime = self.clock.getTime() self.clockLatch = self.clockRegister = 0 self.clockSeconds = self.clockMinutes = self.clockHours = self.clockDays = self.clockControl = 0 @@ -417,11 +448,11 @@ self.writeClockData(address, data) def writeRAMEnable(self, address, data): - if (self.ramSize > 0): + if self.ramSize > 0: self.ramEnable = ((data & 0x0A) == 0x0A) def writeROMBank(self, address, data): - if (data == 0): + if data == 0: data = 1 self.romBank = ((data & 0x7F) << 14) & self.romSize @@ -492,6 +523,10 @@ self.clockControl |= 0x80 self.clockTime = now + +#------------------------------------------------------------------------------- + + class MBC5(MBC): """ PyBoy GameBoy (TM) Emulator @@ -510,7 +545,7 @@ self.maxRomBankSize = 512 self.rumble = rumble - super.__init__(rom, ram, clockDriver) + MBC.__init__(self, rom, ram, clockDriver) def write(self, address, data): @@ -535,10 +570,20 @@ else: self.ramBank = ((data & 0x0F) << 13) & self.ramSize + +#------------------------------------------------------------------------------- + + class HuC1(MBC): def __init__(self, ram, rom, clockDriver): self.reset() - super.__init__(rom, ram, clockDriver) + MBC.__init__(self, rom, ram, clockDriver) + + + +#------------------------------------------------------------------------------- + + class HuC3(MBC): """ @@ -565,11 +610,11 @@ self.setRAM(ram) self.ramFlag = 0 self.ramValue = 0 - super.__init__(rom, ram, clockDriver) + MBC.__init__(self, rom, ram, clockDriver) - def reset(): - super.reset() + def reset(self): + MBC.reset(self) self.ramFlag = 0 self.ramValue = 0 self.clockRegister = 0 @@ -668,8 +713,10 @@ self.clockRegister += (1 << 24) - (365 << 12) self.clockTime = now - elapsed + # MEMORY BANK MAPPING ---------------------------------------------------------- + MEMORY_BANK_TYPE_RANGES = [ (constants.TYPE_MBC1, constants.TYPE_MBC1_RAM_BATTERY, MBC1), (constants.TYPE_MBC2, constants.TYPE_MBC2_BATTERY, MBC2), @@ -681,7 +728,7 @@ def initialize_mapping_table(): - result = [None] * 256 + result = [DefaultMBC] * 256 for entry in MEMORY_BANK_TYPE_RANGES: if len(entry) == 2: positions = [entry[0]] Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/constants.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/constants.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/constants.py Sat May 3 16:47:04 2008 @@ -41,9 +41,9 @@ TYPE_HUC1_RAM_BATTERY = 0xFF CARTRIDGE_TYPE_ADDRESS = 0x0147 -ROM_SIZE_ADDRESS = 0x0148 -RAM_SIZE_ADDRESS = 0x0149 -RAM_SIZE_MAPPING = {0x00:0, 0x01:8192, 0x02:8192, 0x03:32768} +CARTRIDGE_ROM_SIZE_ADDRESS = 0x0148 +CARTRIDGE_RAM_SIZE_ADDRESS = 0x0149 +CARTRIDGE_RAM_SIZE_MAPPING = {0x00:0, 0x01:8192, 0x02:8192, 0x03:32768} DESTINATION_CODE_ADDRESS = 0x014A LICENSEE_ADDRESS = 0x014B ROM_VERSION_ADDRESS = 0x014C Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboy.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboy.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboy.py Sat May 3 16:47:04 2008 @@ -45,6 +45,9 @@ def loadCartridge(self, cartridge): self.cartridgeManager.load(cartridge) + + def loadCartridgeFile(self, path): + self.loadCartridge(Cartridge(path)) def getFrameSkip(self): return self.video.getFrameSkip() @@ -52,8 +55,6 @@ def setFrameSkip(self, frameSkip): self.video.setFrameSkip(frameSkip) - def load(self, cartridgeName): - self.cartridge.load(cartridgeName) def save(self, cartridgeName): self.cartridge.save(cartridgeName) Added: pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_rom.py ============================================================================== --- (empty file) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_rom.py Sat May 3 16:47:04 2008 @@ -0,0 +1,63 @@ + +import py +from pypy.lang.gameboy import constants +from pypy.lang.gameboy.cpu import * +from pypy.lang.gameboy.cartridge import * +from pypy.lang.gameboy.gameboy import * + + +ROM_PATH = str(py.magic.autopath().dirpath().dirpath())+"/rom" + + + +def test_rom1(): + gameBoy = GameBoy() + try: + gameBoy.loadCartridgeFile(ROM_PATH+"/rom1/rom1.raw") + py.test.fail() + except: + pass + + +def test_rom2(): + gameBoy = GameBoy() + try: + gameBoy.loadCartridgeFile(ROM_PATH+"/rom2/rom2.raw") + py.test.fail() + except: + pass + + +def test_rom3(): + gameBoy = GameBoy() + gameBoy.loadCartridgeFile(ROM_PATH+"/rom3/rom3.gb") + + +def test_rom4(): + gameBoy = GameBoy() + gameBoy.loadCartridgeFile(ROM_PATH+"/rom4/rom4.gb") + + +def test_rom5(): + gameBoy = GameBoy() + gameBoy.loadCartridgeFile(ROM_PATH+"/rom5/rom5.gb") + + +def test_rom6(): + gameBoy = GameBoy() + gameBoy.loadCartridgeFile(ROM_PATH+"/rom6/rom6.gb") + + +def test_rom7(): + gameBoy = GameBoy() + gameBoy.loadCartridgeFile(ROM_PATH+"/rom7/rom7.gb") + + +def test_rom8(): + gameBoy = GameBoy() + gameBoy.loadCartridgeFile(ROM_PATH+"/rom8/rom8.gb") + + +def test_rom9(): + gameBoy = GameBoy() + gameBoy.loadCartridgeFile(ROM_PATH+"/rom9/rom9.gb") \ No newline at end of file From antocuni at codespeak.net Sat May 3 16:47:52 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Sat, 3 May 2008 16:47:52 +0200 (CEST) Subject: [pypy-svn] r54373 - pypy/branch/oo-jit/pypy/jit/codegen/test Message-ID: <20080503144752.EBB2B2A0151@codespeak.net> Author: antocuni Date: Sat May 3 16:47:52 2008 New Revision: 54373 Modified: pypy/branch/oo-jit/pypy/jit/codegen/test/rgenop_tests.py Log: remove two debug prints Modified: pypy/branch/oo-jit/pypy/jit/codegen/test/rgenop_tests.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/codegen/test/rgenop_tests.py (original) +++ pypy/branch/oo-jit/pypy/jit/codegen/test/rgenop_tests.py Sat May 3 16:47:52 2008 @@ -2087,10 +2087,8 @@ builder2.finish_and_goto([v33, v9, v10], label1) - print 'waatch!' builder8.start_writing() builder8.finish_and_goto([v10, v9, v9], label4) - print 'stop!' builder7.start_writing() builder7.finish_and_goto([v24, v4, v5], label0) From antocuni at codespeak.net Sat May 3 17:04:06 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Sat, 3 May 2008 17:04:06 +0200 (CEST) Subject: [pypy-svn] r54374 - in pypy/branch/oo-jit/pypy/jit: codegen/cli/test rainbow/test Message-ID: <20080503150406.6CDC02A0151@codespeak.net> Author: antocuni Date: Sat May 3 17:04:05 2008 New Revision: 54374 Added: pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_interpreter.py (contents, props changed) Modified: pypy/branch/oo-jit/pypy/jit/rainbow/test/test_interpreter.py Log: port rainbow tests to cli, to be run under pythonnet Added: pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_interpreter.py ============================================================================== --- (empty file) +++ pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_interpreter.py Sat May 3 17:04:05 2008 @@ -0,0 +1,91 @@ +import py +from pypy.jit.codegen.cli.rgenop import RCliGenOp +from pypy.jit.rainbow.test.test_interpreter import TestOOType as RainbowTest + +class TestRainbowCli(RainbowTest): + RGenOp = RCliGenOp + + # for the individual tests see + # ====> ../../../rainbow/test/test_interpreter.py + + def run_generated(self, writer, generated, residualargs, **kwds): + if 'check_raises' not in kwds: + res = generated(*residualargs) + else: + assert False, 'TODO' + return res + + def check_insns(self, expected=None, **counts): + "Cannot check instructions in the generated assembler." + + def skip(self): + py.test.skip('in progress') + + test_simple_opt_const_propagation1 = skip + test_simple_opt_const_propagation2 = skip + test_simple_fixed = skip + test_red_switch = skip + test_merge = skip + test_loop_merging = skip + test_loop_merging2 = skip + test_two_loops_merging = skip + test_green_across_split = skip + test_merge_const_before_return = skip + test_merge_3_redconsts_before_return = skip + test_merge_const_at_return = skip + test_call_4 = skip + test_call_5 = skip + test_call_6 = skip + test_green_call = skip + test_green_call_void_return = skip + test_split_on_green_return = skip + test_simple_struct = skip + test_complex_struct = skip + test_simple_array = skip + test_arraysize = skip + test_degenerate_with_voids = skip + test_red_virtual_container = skip + test_setarrayitem = skip + test_red_propagate = skip + test_merge_structures = skip + test_green_with_side_effects = skip + test_compile_time_const_tuple = skip + test_green_deepfrozen_oosend = skip + test_direct_oosend_with_green_self = skip + test_residual_red_call = skip + test_residual_red_call_with_exc = skip + test_simple_meth = skip + test_simple_red_meth = skip + test_simple_red_meth_vars_around = skip + test_simple_indirect_call = skip + test_normalize_indirect_call = skip + test_normalize_indirect_call_more = skip + test_green_char_at_merge = skip + test_self_referential_structures = skip + test_known_nonzero = skip + test_debug_assert_ptr_nonzero = skip + test_indirect_red_call = skip + test_indirect_red_call_with_exc = skip + test_indirect_gray_call = skip + test_indirect_residual_red_call = skip + test_constant_indirect_red_call = skip + test_constant_indirect_red_call_no_result = skip + test_indirect_sometimes_residual_pure_red_call = skip + test_indirect_sometimes_residual_pure_but_fixed_red_call = skip + test_manual_marking_of_pure_functions = skip + test_red_int_add_ovf = skip + test_nonzeroness_assert_while_compiling = skip + test_segfault_while_compiling = skip + test_switch = skip + test_switch_char = skip + test_learn_boolvalue = skip + test_learn_nonzeroness = skip + test_freeze_booleffects_correctly = skip + test_ptrequality = skip + test_green_ptrequality = skip + test_void_args = skip + test_degenerated_before_return = skip + test_degenerated_before_return_2 = skip + test_degenerated_at_return = skip + test_degenerated_via_substructure = skip + test_red_subclass = skip Modified: pypy/branch/oo-jit/pypy/jit/rainbow/test/test_interpreter.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/rainbow/test/test_interpreter.py (original) +++ pypy/branch/oo-jit/pypy/jit/rainbow/test/test_interpreter.py Sat May 3 17:04:05 2008 @@ -233,6 +233,9 @@ writer.interpreter.finish_jitstate(sigtoken) builder.end() generated = gv_generated.revealconst(self.Ptr(self.RESIDUAL_FUNCTYPE)) + return self.run_generated(writer, generated, residualargs, **kwds) + + def run_generated(self, writer, generated, residualargs, **kwds): graph = get_funcobj(generated).graph self.residual_graph = graph if conftest.option.view: From antocuni at codespeak.net Sat May 3 17:17:09 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Sat, 3 May 2008 17:17:09 +0200 (CEST) Subject: [pypy-svn] r54375 - in pypy/branch/oo-jit/pypy: annotation jit/codegen/cli/test translator/cli translator/cli/src Message-ID: <20080503151709.D6BE62A0151@codespeak.net> Author: antocuni Date: Sat May 3 17:17:07 2008 New Revision: 54375 Modified: pypy/branch/oo-jit/pypy/annotation/bookkeeper.py pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_interpreter.py pypy/branch/oo-jit/pypy/translator/cli/dotnet.py pypy/branch/oo-jit/pypy/translator/cli/src/pypylib.cs Log: test_simple_fixed passes; we need to use DynamicInvoke to call the delegate, else the result is wrong (not sure if it's a mono or pythonnet bug) Modified: pypy/branch/oo-jit/pypy/annotation/bookkeeper.py ============================================================================== --- pypy/branch/oo-jit/pypy/annotation/bookkeeper.py (original) +++ pypy/branch/oo-jit/pypy/annotation/bookkeeper.py Sat May 3 17:17:07 2008 @@ -8,7 +8,7 @@ from pypy.objspace.flow.model import Constant from pypy.annotation.model import SomeString, SomeChar, SomeFloat, \ SomePtr, unionof, SomeInstance, SomeDict, SomeBuiltin, SomePBC, \ - SomeInteger, SomeOOInstance, TLS, SomeAddress, \ + SomeInteger, SomeOOInstance, SomeOOObject, TLS, SomeAddress, \ SomeUnicodeCodePoint, SomeOOStaticMeth, s_None, s_ImpossibleValue, \ SomeLLADTMeth, SomeBool, SomeTuple, SomeOOClass, SomeImpossibleValue, \ SomeUnicodeString, SomeList, SomeObject, HarmlesslyBlocked, \ @@ -417,6 +417,8 @@ result = SomeOOInstance(ootype.typeOf(x)) elif isinstance(x, (ootype._record, ootype._string)): result = SomeOOInstance(ootype.typeOf(x)) + elif isinstance(x, (ootype._object)): + result = SomeOOObject() elif callable(x): if hasattr(x, '__self__') and x.__self__ is not None: # for cases like 'l.append' where 'l' is a global constant list Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_interpreter.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_interpreter.py (original) +++ pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_interpreter.py Sat May 3 17:17:07 2008 @@ -10,7 +10,7 @@ def run_generated(self, writer, generated, residualargs, **kwds): if 'check_raises' not in kwds: - res = generated(*residualargs) + res = generated.DynamicInvoke(residualargs) else: assert False, 'TODO' return res @@ -23,7 +23,6 @@ test_simple_opt_const_propagation1 = skip test_simple_opt_const_propagation2 = skip - test_simple_fixed = skip test_red_switch = skip test_merge = skip test_loop_merging = skip Modified: pypy/branch/oo-jit/pypy/translator/cli/dotnet.py ============================================================================== --- pypy/branch/oo-jit/pypy/translator/cli/dotnet.py (original) +++ pypy/branch/oo-jit/pypy/translator/cli/dotnet.py Sat May 3 17:17:07 2008 @@ -711,6 +711,7 @@ CLR._buildtree() known_delegates = { + ootype.StaticMethod([], ootype.Signed): CLR.pypy.test.DelegateType_int__0, ootype.StaticMethod([ootype.Signed, ootype.Float], ootype.Float): CLR.pypy.test.DelegateType_double_int_double, ootype.StaticMethod([ootype.Float], ootype.Float): CLR.pypy.test.DelegateType_double__double_1, ootype.StaticMethod([ootype.Signed], ootype.Void): CLR.pypy.test.DelegateType_void_int_1, Modified: pypy/branch/oo-jit/pypy/translator/cli/src/pypylib.cs ============================================================================== --- pypy/branch/oo-jit/pypy/translator/cli/src/pypylib.cs (original) +++ pypy/branch/oo-jit/pypy/translator/cli/src/pypylib.cs Sat May 3 17:17:07 2008 @@ -82,6 +82,7 @@ } } + public delegate double DelegateType_int__0(); public delegate double DelegateType_double__double_1(double a); public delegate double DelegateType_double_int_double(int a, double b); public delegate void DelegateType_void_int_1(int a); From cami at codespeak.net Sat May 3 17:19:39 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Sat, 3 May 2008 17:19:39 +0200 (CEST) Subject: [pypy-svn] r54376 - in pypy/branch/gameboy-emulator/pypy/lang/gameboy: . test Message-ID: <20080503151939.425FA2A0151@codespeak.net> Author: cami Date: Sat May 3 17:19:38 2008 New Revision: 54376 Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboy.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/joypad.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_rom.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/timer.py Log: started to complete rom test bug in cpu/ram read returns None bug fixes Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py Sat May 3 17:19:38 2008 @@ -80,7 +80,10 @@ def getMemoryBankType(self): return self.rom[constants.CARTRIDGE_TYPE_ADDRESS] & 0xFF - def getRom(self): + def getMemoryBank(self): + return self.mbc + + def getROM(self): return self.rom def getROMSize(self): @@ -130,6 +133,8 @@ return MEMORY_BANK_MAPPING[type](rom, ram, clockDriver) +# ------------------------------------------------------------------------------ + class Cartridge(object): """ Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py Sat May 3 17:19:38 2008 @@ -207,7 +207,8 @@ self.a = Register(self, constants.RESET_A) self.f = FlagRegister(self) self.af = DoubleRegister(self, self.a, self.f) - + + self.rom = [] self.reset() def reset(self): @@ -319,8 +320,8 @@ def emulate(self, ticks): self.cycles += ticks self.handlePendingInterrupt() - while (self.cycles > 0): - self.execute() + while self.cycles > 0: + self.execute(self.fetch()) # Interrupts def handlePendingInterrupt(self): Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboy.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboy.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboy.py Sat May 3 17:19:38 2008 @@ -1,7 +1,7 @@ """ PyBoy GameBoy (TM) Emulator -Gameboy Scheduler and Memory Mapper +GameBoy Scheduler and Memory Mapper """ from pypy.lang.gameboy import constants @@ -26,25 +26,26 @@ def createDrivers(self): self.clock = Clock() self.joypadDriver = JoypadDriver() - self.videoDriver = VideoDriver() - self.soundDriver = SoundDriver() + self.videoDriver = VideoDriver() + self.soundDriver = SoundDriver() def createGamboyElements(self): - self.ram = RAM() + self.ram = RAM() self.cartridgeManager = CartridgeManager(self.clock) self.interrupt = Interrupt() - self.cpu = CPU(self.interrupt, self) + self.cpu = CPU(self.interrupt, self) self.serial = Serial(self.interrupt) - self.timer = Timer(self.interrupt) + self.timer = Timer(self.interrupt) self.joypad = Joypad(self.joypadDriver, self.interrupt) - self.video = Video(self.videoDriver, self.interrupt, self) - self.sound = Sound(self.soundDriver) + self.video = Video(self.videoDriver, self.interrupt, self) + self.sound = Sound(self.soundDriver) def getCartridgeManager(self): return self.cartridgeManager def loadCartridge(self, cartridge): self.cartridgeManager.load(cartridge) + self.cpu.setROM(self.cartridgeManager.getROM()) def loadCartridgeFile(self, path): self.loadCartridge(Cartridge(path)) @@ -55,7 +56,6 @@ def setFrameSkip(self, frameSkip): self.video.setFrameSkip(frameSkip) - def save(self, cartridgeName): self.cartridge.save(cartridgeName) @@ -75,16 +75,16 @@ self.joypad.reset() self.video.reset() self.sound.reset() - self.cpu.setROM(self.cartridge.getROM()) + self.cpu.setROM(self.cartridgeManager.getROM()) self.drawLogo() def cycles(self): - return min( self.video.cycles(), self.serial.cycles(), - self.timer.cycles(), self.sound.cycles(), - self.joypad.cycles()) + return min( self.video.getCycles(), self.serial.getCycles(), + self.timer.getCycles(), self.sound.getCycles(), + self.joypad.getCycles()) def emulate(self, ticks): - while (ticks > 0): + while ticks > 0: count = self.cycles() self.cpu.emulate(count) self.serial.emulate(count) @@ -95,38 +95,38 @@ ticks -= count def write(self, address, data): - self.getreceiver(address).write(address, data) + self.getReceiver(address).write(address, data) def read(self, address): - self.getreceiver(address).read(address) + self.getReceiver(address).read(address) - def getreceiver(self, address): + def getReceiver(self, address): if 0x0000 <= address <= 0x7FFF: - return Gameboy.cartridge + return self.cartridgeManager.getMemoryBank() elif 0x8000 <= address <= 0x9FFF: - return Gameboy.video + return self.video elif 0xA000 <= address <= 0xBFFF: - return Gameboy.cartridge + return self.cartridgeManager.getMemoryBank() elif 0xC000 <= address <= 0xFDFF: - return Gameboy.ram + return self.ram elif 0xFE00 <= address <= 0xFEFF: - return Gameboy.video + return self.video elif 0xFF00 <= address <= 0xFF00: - return Gameboy.joypad + return self.joypad elif 0xFF01 <= address <= 0xFF02: - return Gameboy.serial + return self.serial elif 0xFF04 <= address <= 0xFF07: - return Gameboy.timer + return self.timer elif 0xFF0F <= address <= 0xFF0F: - return Gameboy.interrupt + return self.interrupt elif 0xFF10 <= address <= 0xFF3F: - return Gameboy.sound + return self.sound elif 0xFF40 <= address <= 0xFF4B: - return Gameboy.video + return self.video elif 0xFF80 <= address <= 0xFFFE: - return Gameboy.ram + return self.ram elif 0xFFFF <= address <= 0xFFFF: - return Gameboy.interrupt + return self.interrupt def drawLogo(self): for index in range(0, 48): Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/joypad.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/joypad.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/joypad.py Sat May 3 17:19:38 2008 @@ -18,7 +18,7 @@ self.buttonCode = 0xF self.cycles = constants.JOYPAD_CLOCK - def cycles(self): + def getCycles(self): return self.cycles def emulate(self, ticks): Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py Sat May 3 17:19:38 2008 @@ -551,7 +551,7 @@ def stop(self): self.driver.stop() - def cycles(self): + def getCycles(self): return self.cycles def emulate(self, ticks): Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_rom.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_rom.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_rom.py Sat May 3 17:19:38 2008 @@ -7,7 +7,9 @@ ROM_PATH = str(py.magic.autopath().dirpath().dirpath())+"/rom" +EMULATION_CYCLES = 64 +# ------------------------------------------------------------------------------ def test_rom1(): @@ -29,35 +31,47 @@ def test_rom3(): + """ some NOP and an endless loop at the end '""" gameBoy = GameBoy() gameBoy.loadCartridgeFile(ROM_PATH+"/rom3/rom3.gb") + gameBoy.emulate(EMULATION_CYCLES) def test_rom4(): gameBoy = GameBoy() gameBoy.loadCartridgeFile(ROM_PATH+"/rom4/rom4.gb") + gameBoy.emulate(EMULATION_CYCLES) def test_rom5(): gameBoy = GameBoy() gameBoy.loadCartridgeFile(ROM_PATH+"/rom5/rom5.gb") + gameBoy.emulate(EMULATION_CYCLES) def test_rom6(): gameBoy = GameBoy() gameBoy.loadCartridgeFile(ROM_PATH+"/rom6/rom6.gb") + gameBoy.emulate(EMULATION_CYCLES) def test_rom7(): + py.test.skip("cpu bug in storeMemoryAtExpandedFetchAddressInA") gameBoy = GameBoy() gameBoy.loadCartridgeFile(ROM_PATH+"/rom7/rom7.gb") + gameBoy.emulate(EMULATION_CYCLES) def test_rom8(): + py.test.skip("cpu bug in storeMemoryAtExpandedFetchAddressInA") gameBoy = GameBoy() gameBoy.loadCartridgeFile(ROM_PATH+"/rom8/rom8.gb") + gameBoy.emulate(EMULATION_CYCLES) def test_rom9(): + py.test.skip("cpu bug in storeMemoryAtExpandedFetchAddressInA") gameBoy = GameBoy() - gameBoy.loadCartridgeFile(ROM_PATH+"/rom9/rom9.gb") \ No newline at end of file + gameBoy.loadCartridgeFile(ROM_PATH+"/rom9/rom9.gb") + gameBoy.emulate(EMULATION_CYCLES) + Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/timer.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/timer.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/timer.py Sat May 3 17:19:38 2008 @@ -65,8 +65,8 @@ self.timerClock = self.timerCycles = constants.TIMER_CLOCK[data & 0x03] self.tac = data - def cycles(self): - if ((self.tac & 0x04) != 0 and self.timerCycles < self.dividerCycles): + def getCycles(self): + if (self.tac & 0x04) != 0 and self.timerCycles < self.dividerCycles: return self.timerCycles return self.dividerCycles From cami at codespeak.net Sat May 3 17:21:20 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Sat, 3 May 2008 17:21:20 +0200 (CEST) Subject: [pypy-svn] r54377 - pypy/branch/gameboy-emulator/pypy/lang/gameboy/test Message-ID: <20080503152120.E7D212A8007@codespeak.net> Author: cami Date: Sat May 3 17:21:20 2008 New Revision: 54377 Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_timer.py Log: updated timer test to the uniform getCycles() instead of cycles() Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_timer.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_timer.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_timer.py Sat May 3 17:21:20 2008 @@ -79,11 +79,11 @@ timer = get_timer() value = 10 timer.dividerCycles = value - assert timer.cycles() == timer.dividerCycles + assert timer.getCycles() == timer.dividerCycles timer.tac = 0x04 timer.timerCycles = value-1 timer.timerCycles = value - assert timer.cycles() == timer.timerCycles + assert timer.getCycles() == timer.timerCycles def test_emulateDivider_normal(): timer = get_timer() From arigo at codespeak.net Sat May 3 19:42:57 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 3 May 2008 19:42:57 +0200 (CEST) Subject: [pypy-svn] r54379 - pypy/dist/pypy/config Message-ID: <20080503174257.DC35D2A8083@codespeak.net> Author: arigo Date: Sat May 3 19:42:55 2008 New Revision: 54379 Modified: pypy/dist/pypy/config/pypyoption.py Log: Option no longer used (and undocumented, making test_pypyoption fail) Modified: pypy/dist/pypy/config/pypyoption.py ============================================================================== --- pypy/dist/pypy/config/pypyoption.py (original) +++ pypy/dist/pypy/config/pypyoption.py Sat May 3 19:42:55 2008 @@ -253,9 +253,6 @@ requires=[("objspace.std.withrangelist", False), ("objspace.name", "std"), ("objspace.std.withtproxy", False)]), - BoolOption("withmultituple", - "use tuples optimized for sizes", - default=False), BoolOption("withfastslice", "make list slicing lazy", default=False, From arigo at codespeak.net Sat May 3 20:45:39 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 3 May 2008 20:45:39 +0200 (CEST) Subject: [pypy-svn] r54381 - pypy/dist/pypy/rpython/memory/gc Message-ID: <20080503184539.78660168544@codespeak.net> Author: arigo Date: Sat May 3 20:45:37 2008 New Revision: 54381 Modified: pypy/dist/pypy/rpython/memory/gc/generation.py pypy/dist/pypy/rpython/memory/gc/hybrid.py Log: Add nice DEBUG_PRINTs to the hybrid gc. Modified: pypy/dist/pypy/rpython/memory/gc/generation.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gc/generation.py (original) +++ pypy/dist/pypy/rpython/memory/gc/generation.py Sat May 3 20:45:37 2008 @@ -1,6 +1,7 @@ import sys from pypy.rpython.memory.gc.semispace import SemiSpaceGC from pypy.rpython.memory.gc.semispace import GCFLAG_EXTERNAL, GCFLAG_FORWARDED +from pypy.rpython.memory.gc.semispace import DEBUG_PRINT from pypy.rpython.lltypesystem.llmemory import NULL, raw_malloc_usage from pypy.rpython.lltypesystem import lltype, llmemory, llarena from pypy.rpython.memory.support import DEFAULT_CHUNK_SIZE @@ -19,8 +20,6 @@ # of static roots yet, but will appear with write barrier GCFLAG_NO_HEAP_PTRS = SemiSpaceGC.first_unused_gcflag << 1 -DEBUG_PRINT = False - class GenerationGC(SemiSpaceGC): """A basic generational GC: it's a SemiSpaceGC with an additional nursery for young objects. A write barrier is used to ensure that Modified: pypy/dist/pypy/rpython/memory/gc/hybrid.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gc/hybrid.py (original) +++ pypy/dist/pypy/rpython/memory/gc/hybrid.py Sat May 3 20:45:37 2008 @@ -1,9 +1,11 @@ import sys from pypy.rpython.memory.gc.semispace import SemiSpaceGC +from pypy.rpython.memory.gc.semispace import DEBUG_PRINT from pypy.rpython.memory.gc.generation import GenerationGC, GCFLAG_FORWARDED from pypy.rpython.memory.gc.generation import GCFLAG_NO_YOUNG_PTRS -from pypy.rpython.lltypesystem import llmemory, llarena +from pypy.rpython.lltypesystem import lltype, llmemory, llarena from pypy.rpython.lltypesystem.llmemory import raw_malloc_usage +from pypy.rpython.lltypesystem.lloperation import llop from pypy.rlib.debug import ll_assert from pypy.rlib.rarithmetic import ovfcheck @@ -48,6 +50,8 @@ assert self.nonlarge_gcptrs_max <= self.lb_young_var_basesize assert self.nonlarge_max <= self.nonlarge_gcptrs_max self.large_objects_collect_trigger = self.space_size + if DEBUG_PRINT: + self._initial_trigger = self.large_objects_collect_trigger self.pending_external_object_list = self.AddressDeque() def setup(self): @@ -153,6 +157,11 @@ # XXX more than the current self.space_size. self.large_objects_collect_trigger -= raw_malloc_usage(totalsize) if self.large_objects_collect_trigger < 0: + if DEBUG_PRINT: + llop.debug_print(lltype.Void, "allocated", + self._initial_trigger - + self.large_objects_collect_trigger, + "bytes, triggering full collection") self.semispace_collect() result = self.allocate_external_object(totalsize) if not result: @@ -178,6 +187,9 @@ # this bit set. ll_assert(not self.pending_external_object_list.non_empty(), "pending_external_object_list should be empty at start") + if DEBUG_PRINT: + self._nonmoving_copy_count = 0 + self._nonmoving_copy_size = 0 def surviving(self, obj): # To use during a collection. The objects that survive are the @@ -220,6 +232,9 @@ # NB. the object can have a finalizer or be a weakref, but # it's not an issue. totalsize = self.size_gc_header() + objsize + if DEBUG_PRINT: + self._nonmoving_copy_count += 1 + self._nonmoving_copy_size += raw_malloc_usage(totalsize) newaddr = self.allocate_external_object(totalsize) if not newaddr: return llmemory.NULL # can't raise MemoryError during a collect() @@ -253,12 +268,18 @@ # free all mark-n-sweep-managed objects that have not been marked large_objects = self.large_objects_list remaining_large_objects = self.AddressDeque() + if DEBUG_PRINT: alive_count = alive_size = 0 + if DEBUG_PRINT: dead_count = dead_size = 0 while large_objects.non_empty(): obj = large_objects.popleft() if self.header(obj).tid & GCFLAG_UNVISITED: + if DEBUG_PRINT:dead_count+=1 + if DEBUG_PRINT:dead_size+=raw_malloc_usage(self.get_size(obj)) addr = obj - self.gcheaderbuilder.size_gc_header llmemory.raw_free(addr) else: + if DEBUG_PRINT:alive_count+=1 + if DEBUG_PRINT:alive_size+=raw_malloc_usage(self.get_size(obj)) self.header(obj).tid |= GCFLAG_UNVISITED remaining_large_objects.append(obj) large_objects.delete() @@ -266,3 +287,18 @@ # As we just collected, it's fine to raw_malloc'ate up to space_size # bytes again before we should force another collect. self.large_objects_collect_trigger = self.space_size + + if DEBUG_PRINT: + self._initial_trigger = self.large_objects_collect_trigger + llop.debug_print(lltype.Void, + "| [hybrid] made nonmoving: ", + self._nonmoving_copy_size, "bytes in", + self._nonmoving_copy_count, "objs") + llop.debug_print(lltype.Void, + "| [hybrid] nonmoving now alive: ", + alive_size, "bytes in", + alive_count, "objs") + llop.debug_print(lltype.Void, + "| [hybrid] nonmoving freed: ", + dead_size, "bytes in", + dead_count, "objs") From arigo at codespeak.net Sat May 3 21:30:56 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 3 May 2008 21:30:56 +0200 (CEST) Subject: [pypy-svn] r54382 - pypy/branch/gc-tweak Message-ID: <20080503193056.F2EA3169EB0@codespeak.net> Author: arigo Date: Sat May 3 21:30:54 2008 New Revision: 54382 Added: pypy/branch/gc-tweak/ - copied from r54381, pypy/dist/ Log: A branch in which to tweak a bit the GCs. From arigo at codespeak.net Sat May 3 22:46:14 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 3 May 2008 22:46:14 +0200 (CEST) Subject: [pypy-svn] r54384 - pypy/branch/gc-tweak/pypy/rpython/memory/gc Message-ID: <20080503204614.59D74168554@codespeak.net> Author: arigo Date: Sat May 3 22:46:12 2008 New Revision: 54384 Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gc/hybrid.py Log: What occurs if we try larger thresholds for the number of times an object must be copied before we make it nonmovable? Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gc/hybrid.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/memory/gc/hybrid.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/memory/gc/hybrid.py Sat May 3 22:46:12 2008 @@ -9,8 +9,22 @@ from pypy.rlib.debug import ll_assert from pypy.rlib.rarithmetic import ovfcheck +# The "age" of an object is the number of times it is copied between the +# two semispaces. When an object would reach MAX_SEMISPACE_AGE, it is +# instead copied to a nonmoving location. For example, a value of 4 +# ensures that an object is copied at most 5 times in total: from the +# nursery to the semispace, then three times between the two spaces, +# then one last time to a nonmoving location. +MAX_SEMISPACE_AGE = 4 + GCFLAG_UNVISITED = GenerationGC.first_unused_gcflag << 0 -GCFLAG_AGING = GenerationGC.first_unused_gcflag << 1 +_gcflag_next_bit = GenerationGC.first_unused_gcflag << 1 +GCFLAG_AGE_ONE = _gcflag_next_bit +GCFLAG_AGE_MAX = _gcflag_next_bit * (MAX_SEMISPACE_AGE-1) +GCFLAG_AGE_MASK = 0 +while GCFLAG_AGE_MASK < GCFLAG_AGE_MAX: + GCFLAG_AGE_MASK |= _gcflag_next_bit + _gcflag_next_bit <<= 1 class HybridGC(GenerationGC): @@ -18,7 +32,7 @@ except that objects above a certain size are handled separately: they are allocated via raw_malloc/raw_free in a mark-n-sweep fashion. """ - first_unused_gcflag = GenerationGC.first_unused_gcflag << 2 + first_unused_gcflag = _gcflag_next_bit # the following values override the default arguments of __init__ when # translating to a real backend. @@ -211,17 +225,17 @@ # from the nursery. If they do, we must add the GCFLAG_NO_YOUNG_PTRS. # If they don't, we count how many times they are copied and when # some threshold is reached we make the copy a non-movable "external" - # object. For now we use a single flag GCFLAG_AGING, so threshold==2. + # object. The threshold is MAX_SEMISPACE_AGE. tid = self.header(obj).tid if not (tid & GCFLAG_NO_YOUNG_PTRS): tid |= GCFLAG_NO_YOUNG_PTRS # object comes from the nursery - elif not (tid & GCFLAG_AGING): - tid |= GCFLAG_AGING + elif (tid & GCFLAG_AGE_MASK) < GCFLAG_AGE_MAX: + tid += GCFLAG_AGE_ONE else: newobj = self.make_a_nonmoving_copy(obj, objsize) if newobj: return newobj - tid &= ~GCFLAG_AGING + tid &= ~GCFLAG_AGE_MASK # skip GenerationGC.make_a_copy() as we already did the right # thing about GCFLAG_NO_YOUNG_PTRS newobj = SemiSpaceGC.make_a_copy(self, obj, objsize) From arigo at codespeak.net Sun May 4 11:49:28 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 4 May 2008 11:49:28 +0200 (CEST) Subject: [pypy-svn] r54386 - pypy/dist/pypy/translator/c Message-ID: <20080504094928.0C75C169E34@codespeak.net> Author: arigo Date: Sun May 4 11:49:26 2008 New Revision: 54386 Modified: pypy/dist/pypy/translator/c/genc.py Log: It seems that GNU Make < 3.81 has no function $(abspath). Workaround. Modified: pypy/dist/pypy/translator/c/genc.py ============================================================================== --- pypy/dist/pypy/translator/c/genc.py (original) +++ pypy/dist/pypy/translator/c/genc.py Sun May 4 11:49:26 2008 @@ -875,9 +875,12 @@ profile: \t$(MAKE) CFLAGS="-g -pg $(CFLAGS)" LDFLAGS="-pg $(LDFLAGS)" $(TARGET) +# it seems that GNU Make < 3.81 has no function $(abspath) +ABS_TARGET = $(shell python -c "import sys,os; print os.path.abspath(sys.argv[1])" $(TARGET)) + profopt: \t$(MAKE) CFLAGS="-fprofile-generate $(CFLAGS)" LDFLAGS="-fprofile-generate $(LDFLAGS)" $(TARGET) -\tcd $(PYPYDIR)/translator/goal && $(abspath $(TARGET)) $(PROFOPT) +\tcd $(PYPYDIR)/translator/goal && $(ABS_TARGET) $(PROFOPT) \t$(MAKE) clean_noprof \t$(MAKE) CFLAGS="-fprofile-use $(CFLAGS)" LDFLAGS="-fprofile-use $(LDFLAGS)" $(TARGET) ''' From arigo at codespeak.net Sun May 4 12:11:56 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 4 May 2008 12:11:56 +0200 (CEST) Subject: [pypy-svn] r54390 - pypy/dist/pypy/rpython/memory/gc Message-ID: <20080504101156.A98C8169EEA@codespeak.net> Author: arigo Date: Sun May 4 12:11:56 2008 New Revision: 54390 Modified: pypy/dist/pypy/rpython/memory/gc/hybrid.py Log: Wait before the objects get a bit older before moving them out of the semispaces into raw_malloc'ed memory. This also causes a better behavior of the logic that decides when the semispace size should be doubled. (svn merge -r54382:54384 svn+ssh://codespeak.net/svn/pypy/branch/gc-tweak/pypy) Modified: pypy/dist/pypy/rpython/memory/gc/hybrid.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gc/hybrid.py (original) +++ pypy/dist/pypy/rpython/memory/gc/hybrid.py Sun May 4 12:11:56 2008 @@ -9,8 +9,22 @@ from pypy.rlib.debug import ll_assert from pypy.rlib.rarithmetic import ovfcheck +# The "age" of an object is the number of times it is copied between the +# two semispaces. When an object would reach MAX_SEMISPACE_AGE, it is +# instead copied to a nonmoving location. For example, a value of 4 +# ensures that an object is copied at most 5 times in total: from the +# nursery to the semispace, then three times between the two spaces, +# then one last time to a nonmoving location. +MAX_SEMISPACE_AGE = 4 + GCFLAG_UNVISITED = GenerationGC.first_unused_gcflag << 0 -GCFLAG_AGING = GenerationGC.first_unused_gcflag << 1 +_gcflag_next_bit = GenerationGC.first_unused_gcflag << 1 +GCFLAG_AGE_ONE = _gcflag_next_bit +GCFLAG_AGE_MAX = _gcflag_next_bit * (MAX_SEMISPACE_AGE-1) +GCFLAG_AGE_MASK = 0 +while GCFLAG_AGE_MASK < GCFLAG_AGE_MAX: + GCFLAG_AGE_MASK |= _gcflag_next_bit + _gcflag_next_bit <<= 1 class HybridGC(GenerationGC): @@ -18,7 +32,7 @@ except that objects above a certain size are handled separately: they are allocated via raw_malloc/raw_free in a mark-n-sweep fashion. """ - first_unused_gcflag = GenerationGC.first_unused_gcflag << 2 + first_unused_gcflag = _gcflag_next_bit # the following values override the default arguments of __init__ when # translating to a real backend. @@ -211,17 +225,17 @@ # from the nursery. If they do, we must add the GCFLAG_NO_YOUNG_PTRS. # If they don't, we count how many times they are copied and when # some threshold is reached we make the copy a non-movable "external" - # object. For now we use a single flag GCFLAG_AGING, so threshold==2. + # object. The threshold is MAX_SEMISPACE_AGE. tid = self.header(obj).tid if not (tid & GCFLAG_NO_YOUNG_PTRS): tid |= GCFLAG_NO_YOUNG_PTRS # object comes from the nursery - elif not (tid & GCFLAG_AGING): - tid |= GCFLAG_AGING + elif (tid & GCFLAG_AGE_MASK) < GCFLAG_AGE_MAX: + tid += GCFLAG_AGE_ONE else: newobj = self.make_a_nonmoving_copy(obj, objsize) if newobj: return newobj - tid &= ~GCFLAG_AGING + tid &= ~GCFLAG_AGE_MASK # skip GenerationGC.make_a_copy() as we already did the right # thing about GCFLAG_NO_YOUNG_PTRS newobj = SemiSpaceGC.make_a_copy(self, obj, objsize) From fijal at codespeak.net Sun May 4 13:22:16 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 4 May 2008 13:22:16 +0200 (CEST) Subject: [pypy-svn] r54396 - pypy/branch/lazy-write-barrier Message-ID: <20080504112216.D8A3116857C@codespeak.net> Author: fijal Date: Sun May 4 13:22:16 2008 New Revision: 54396 Removed: pypy/branch/lazy-write-barrier/ Log: Remove merged branch From fijal at codespeak.net Sun May 4 13:49:41 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 4 May 2008 13:49:41 +0200 (CEST) Subject: [pypy-svn] r54397 - pypy/branch/io-improvements/pypy/rpython/lltypesystem Message-ID: <20080504114941.82814168543@codespeak.net> Author: fijal Date: Sun May 4 13:49:39 2008 New Revision: 54397 Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/rstr.py Log: Last occurence of copying characters by hand in rstr. it seems that using raw_memcopy gives some small speedups here and there, but at least we've got string copying in a single place Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/rstr.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/lltypesystem/rstr.py (original) +++ pypy/branch/io-improvements/pypy/rpython/lltypesystem/rstr.py Sun May 4 13:49:39 2008 @@ -238,6 +238,7 @@ times = 0 newstr = malloc(times) j = 0 + # XXX we can use memset here, not sure how useful this is while j < times: newstr.chars[j] = ch j += 1 @@ -594,8 +595,10 @@ i += 1 if typeOf(items).TO.OF.TO == STR: malloc = mallocstr + copy_contents = copy_string_contents else: malloc = mallocunicode + copy_contents = copy_unicode_contents result = malloc(itemslen) res_chars = result.chars res_index = 0 @@ -603,15 +606,14 @@ while i < num_items: item_chars = items[i].chars item_len = len(item_chars) - j = 0 - while j < item_len: - res_chars[res_index] = item_chars[j] - j += 1 - res_index += 1 + copy_contents(result, items[i], res_index, 0, item_len) + res_index += item_len i += 1 return result def ll_join_chars(length, chars): + # no need to optimize this, will be replaced by string builder + # at some point soon num_chars = length if typeOf(chars).TO.OF == Char: malloc = mallocstr From fijal at codespeak.net Sun May 4 14:11:27 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 4 May 2008 14:11:27 +0200 (CEST) Subject: [pypy-svn] r54398 - in pypy/branch/io-improvements/pypy/rlib: . test Message-ID: <20080504121127.4F1CD169ECC@codespeak.net> Author: fijal Date: Sun May 4 14:11:26 2008 New Revision: 54398 Modified: pypy/branch/io-improvements/pypy/rlib/rgc.py pypy/branch/io-improvements/pypy/rlib/test/test_rgc.py Log: Change interface of string builder a bit. I'm not sure exactly if this is ok, because we return a pointer and than we resize a pointer. Reasoning behind it is that we return a *new* pointer which might actually be the same. (So array really does not change it's size) Modified: pypy/branch/io-improvements/pypy/rlib/rgc.py ============================================================================== --- pypy/branch/io-improvements/pypy/rlib/rgc.py (original) +++ pypy/branch/io-improvements/pypy/rlib/rgc.py Sun May 4 14:11:26 2008 @@ -233,47 +233,72 @@ hop.exception_cannot_occur() return hop.genop(opname, vlist, resulttype = hop.r_result.lowleveltype) -def raw_array_of_shape(T, init_size): +def raw_buffer_of_shape(T, init_size): """ Allocates a raw array of given shape. This array is suitable for resizing by resize_raw_array or finalizing calling cast_raw_array_to_shape """ from pypy.rpython.lltypesystem import lltype - return lltype.malloc(lltype.Array(lltype.Char, hints={'nolength':True}), - init_size, flavor='raw') + return lltype.malloc(T, init_size) -class RawArrayOfShapeEntry(ExtRegistryEntry): - _about_ = raw_array_of_shape +class RawBufferOfShapeEntry(ExtRegistryEntry): + _about_ = raw_buffer_of_shape -def resize_raw_array(arr, old_size, new_size): + def compute_result_annotation(self, s_T, s_init_size): + from pypy.annotation import model as annmodel + from pypy.rpython.lltypesystem import rffi + assert s_T.is_constant() + assert isinstance(s_init_size, annmodel.SomeInteger) + T = s_T.const + return annmodel.SomePtr(T) + + def specialize_call(self, hop): + xxx + #T = hop.args_v[0].value + #hop.genop('malloc_raw_array', + +def resize_buffer(ptr, new_size): """ Resize raw array returned by raw_array_of_shape from old_size to new_size. Returns pointer to new array (in case resizing copied contents of old array to new place """ from pypy.rpython.lltypesystem import lltype + T = lltype.typeOf(ptr).TO + arrayfld = T._arrayfld + arr = getattr(ptr, arrayfld) + old_size = len(arr) # we don't have any realloc on top of cpython - new_ar = lltype.malloc(lltype.Array(lltype.Char, hints={'nolength':True}), - new_size, flavor='raw') + new_ptr = lltype.malloc(T, new_size) + new_ar = getattr(new_ptr, arrayfld) for i in range(old_size): new_ar[i] = arr[i] - lltype.free(arr, flavor='raw') - return new_ar + return new_ptr + +class ResizeBufferEntry(ExtRegistryEntry): + _about_ = resize_buffer -class ResizeRawArrayEntry(ExtRegistryEntry): - _about_ = resize_raw_array + def compute_result_annotation(self, s_arr, s_old_size, s_new_size): + from pypy.annotation import model as annmodel + from pypy.rpython.lltypesystem import rffi + assert isinstance(s_arr, annmodel.SomePtr) + assert isinstance(s_old_size, annmodel.SomeInteger) + assert isinstance(s_new_size, annmodel.SomeInteger) + assert s_arr.ll_ptrtype is rffi.VOIDP + return s_arr -def cast_raw_array_to_shape(T, arr, size): +def finish_building_buffer(T, ptr): """ Cast raw array returned by raw_array_of_shape to type T. """ - from pypy.rpython.lltypesystem import lltype - res = lltype.malloc(T, size) - if isinstance(T, lltype.Array): - array_elem = res - elif isinstance(T, lltype.Struct): - array_elem = getattr(res, T._arrayfld) - else: - raise TypeError("Cannot cast %s" % T) - for num in range(size): - array_elem[num] = arr[num] - return res + return ptr + +class FinishBuildingBufferEntry(ExtRegistryEntry): + _about_ = finish_building_buffer + def compute_result_annotation(self, s_T, s_arr, s_size): + from pypy.annotation.model import SomePtr, SomeInteger + from pypy.rpython.lltypesystem import lltype + assert s_T.is_constant() + T = s_T.const + assert isinstance(s_arr, SomePtr) + assert isinstance(s_size, SomeInteger) + return SomePtr(lltype.Ptr(T)) Modified: pypy/branch/io-improvements/pypy/rlib/test/test_rgc.py ============================================================================== --- pypy/branch/io-improvements/pypy/rlib/test/test_rgc.py (original) +++ pypy/branch/io-improvements/pypy/rlib/test/test_rgc.py Sun May 4 14:11:26 2008 @@ -42,10 +42,10 @@ from pypy.rpython.annlowlevel import hlstr def f(): - arr = rgc.raw_array_of_shape(STR, 1) - arr[0] = 'a' - arr = rgc.resize_raw_array(arr, 1, 2) - arr[1] = 'b' - return hlstr(rgc.cast_raw_array_to_shape(STR, arr, 2)) + ptr = rgc.raw_buffer_of_shape(STR, 1) + ptr.chars[0] = 'a' + ptr = rgc.resize_buffer(ptr, 2) + ptr.chars[1] = 'b' + return hlstr(rgc.finish_building_buffer(STR, ptr)) assert f() == 'ab' From fijal at codespeak.net Sun May 4 14:19:41 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 4 May 2008 14:19:41 +0200 (CEST) Subject: [pypy-svn] r54399 - pypy/branch/io-improvements/pypy/rlib Message-ID: <20080504121941.2195D2A8086@codespeak.net> Author: fijal Date: Sun May 4 14:19:40 2008 New Revision: 54399 Modified: pypy/branch/io-improvements/pypy/rlib/rgc.py Log: adapt docstrings Modified: pypy/branch/io-improvements/pypy/rlib/rgc.py ============================================================================== --- pypy/branch/io-improvements/pypy/rlib/rgc.py (original) +++ pypy/branch/io-improvements/pypy/rlib/rgc.py Sun May 4 14:19:40 2008 @@ -234,9 +234,8 @@ return hop.genop(opname, vlist, resulttype = hop.r_result.lowleveltype) def raw_buffer_of_shape(T, init_size): - """ Allocates a raw array of given shape. This array is suitable - for resizing by resize_raw_array or finalizing calling - cast_raw_array_to_shape + """ Pre-allocates structure of type T (varsized) with possibility + to reallocate it further by resize_buffer. """ from pypy.rpython.lltypesystem import lltype return lltype.malloc(T, init_size) @@ -258,9 +257,7 @@ #hop.genop('malloc_raw_array', def resize_buffer(ptr, new_size): - """ Resize raw array returned by raw_array_of_shape from old_size - to new_size. Returns pointer to new array (in case resizing copied - contents of old array to new place + """ Resize raw buffer returned by raw_buffer_of_shape to new size """ from pypy.rpython.lltypesystem import lltype T = lltype.typeOf(ptr).TO @@ -287,7 +284,7 @@ return s_arr def finish_building_buffer(T, ptr): - """ Cast raw array returned by raw_array_of_shape to type T. + """ Finish building raw_buffer returned by raw_buffer_of_shape """ return ptr From fijal at codespeak.net Sun May 4 14:57:17 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 4 May 2008 14:57:17 +0200 (CEST) Subject: [pypy-svn] r54401 - in pypy/branch/io-improvements/pypy: rlib rlib/test rpython rpython/lltypesystem rpython/memory rpython/memory/test Message-ID: <20080504125717.B173D169E7C@codespeak.net> Author: fijal Date: Sun May 4 14:57:16 2008 New Revision: 54401 Modified: pypy/branch/io-improvements/pypy/rlib/rgc.py pypy/branch/io-improvements/pypy/rlib/test/test_rgc.py pypy/branch/io-improvements/pypy/rpython/llinterp.py pypy/branch/io-improvements/pypy/rpython/lltypesystem/lloperation.py pypy/branch/io-improvements/pypy/rpython/memory/gcwrapper.py pypy/branch/io-improvements/pypy/rpython/memory/test/test_gc.py Log: Enough support to pass test_gc with resizable buffer. It's still not doing too much Modified: pypy/branch/io-improvements/pypy/rlib/rgc.py ============================================================================== --- pypy/branch/io-improvements/pypy/rlib/rgc.py (original) +++ pypy/branch/io-improvements/pypy/rlib/rgc.py Sun May 4 14:57:16 2008 @@ -245,16 +245,19 @@ def compute_result_annotation(self, s_T, s_init_size): from pypy.annotation import model as annmodel - from pypy.rpython.lltypesystem import rffi + from pypy.rpython.lltypesystem import rffi, lltype assert s_T.is_constant() assert isinstance(s_init_size, annmodel.SomeInteger) T = s_T.const - return annmodel.SomePtr(T) + return annmodel.SomePtr(lltype.Ptr(T)) def specialize_call(self, hop): - xxx - #T = hop.args_v[0].value - #hop.genop('malloc_raw_array', + from pypy.rpython.lltypesystem import lltype + vlist = [hop.inputarg(lltype.Void, 0), + hop.inputarg(lltype.Signed, 1)] + hop.exception_is_here() + return hop.genop('malloc_resizable_buffer', vlist, + resulttype=hop.r_result.lowleveltype) def resize_buffer(ptr, new_size): """ Resize raw buffer returned by raw_buffer_of_shape to new size @@ -274,16 +277,22 @@ class ResizeBufferEntry(ExtRegistryEntry): _about_ = resize_buffer - def compute_result_annotation(self, s_arr, s_old_size, s_new_size): + def compute_result_annotation(self, s_ptr, s_new_size): from pypy.annotation import model as annmodel from pypy.rpython.lltypesystem import rffi - assert isinstance(s_arr, annmodel.SomePtr) - assert isinstance(s_old_size, annmodel.SomeInteger) + assert isinstance(s_ptr, annmodel.SomePtr) assert isinstance(s_new_size, annmodel.SomeInteger) - assert s_arr.ll_ptrtype is rffi.VOIDP - return s_arr + return s_ptr -def finish_building_buffer(T, ptr): + def specialize_call(self, hop): + from pypy.rpython.lltypesystem import lltype + vlist = [hop.inputarg(hop.args_r[0], 0), + hop.inputarg(lltype.Signed, 1)] + hop.exception_is_here() + return hop.genop('resize_buffer', vlist, + resulttype=hop.r_result.lowleveltype) + +def finish_building_buffer(ptr): """ Finish building raw_buffer returned by raw_buffer_of_shape """ return ptr @@ -291,11 +300,14 @@ class FinishBuildingBufferEntry(ExtRegistryEntry): _about_ = finish_building_buffer - def compute_result_annotation(self, s_T, s_arr, s_size): - from pypy.annotation.model import SomePtr, SomeInteger - from pypy.rpython.lltypesystem import lltype - assert s_T.is_constant() - T = s_T.const + def compute_result_annotation(self, s_arr): + from pypy.annotation.model import SomePtr, s_ImpossibleValue assert isinstance(s_arr, SomePtr) - assert isinstance(s_size, SomeInteger) - return SomePtr(lltype.Ptr(T)) + return s_arr + + def specialize_call(self, hop): + from pypy.rpython.lltypesystem import lltype + vlist = [hop.inputarg(hop.args_r[0], 0)] + hop.exception_cannot_occur() + return hop.genop('finish_building_buffer', vlist, + resulttype=hop.r_result.lowleveltype) Modified: pypy/branch/io-improvements/pypy/rlib/test/test_rgc.py ============================================================================== --- pypy/branch/io-improvements/pypy/rlib/test/test_rgc.py (original) +++ pypy/branch/io-improvements/pypy/rlib/test/test_rgc.py Sun May 4 14:57:16 2008 @@ -46,6 +46,6 @@ ptr.chars[0] = 'a' ptr = rgc.resize_buffer(ptr, 2) ptr.chars[1] = 'b' - return hlstr(rgc.finish_building_buffer(STR, ptr)) + return hlstr(rgc.finish_building_buffer(ptr)) assert f() == 'ab' Modified: pypy/branch/io-improvements/pypy/rpython/llinterp.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/llinterp.py (original) +++ pypy/branch/io-improvements/pypy/rpython/llinterp.py Sun May 4 14:57:16 2008 @@ -697,6 +697,15 @@ zero = flags.get('zero', False) return self.heap.malloc_nonmovable(obj, size, zero=zero) + def op_malloc_resizable_buffer(self, obj, size): + return self.heap.malloc_resizable_buffer(obj, size) + + def op_resize_buffer(self, obj, new_size): + return self.heap.resize_buffer(obj, new_size) + + def op_finish_building_buffer(self, obj): + return self.heap.finish_building_buffer(obj) + def op_free(self, obj, flavor): assert isinstance(flavor, str) if flavor == 'raw' and self.llinterpreter.malloc_check: Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/lltypesystem/lloperation.py (original) +++ pypy/branch/io-improvements/pypy/rpython/lltypesystem/lloperation.py Sun May 4 14:57:16 2008 @@ -325,6 +325,9 @@ 'malloc_varsize': LLOp(canraise=(MemoryError,), canunwindgc=True), 'malloc_nonmovable': LLOp(canraise=(MemoryError,), canunwindgc=True), 'malloc_nonmovable_varsize':LLOp(canraise=(MemoryError,),canunwindgc=True), + 'malloc_resizable_buffer': LLOp(canraise=(MemoryError,),canunwindgc=True), + 'resize_buffer': LLOp(canraise=(MemoryError,),canunwindgc=True), + 'finish_building_buffer' : LLOp(), 'zero_gc_pointers_inside': LLOp(), 'free': LLOp(), 'getfield': LLOp(sideeffects=False, canrun=True), Modified: pypy/branch/io-improvements/pypy/rpython/memory/gcwrapper.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/memory/gcwrapper.py (original) +++ pypy/branch/io-improvements/pypy/rpython/memory/gcwrapper.py Sun May 4 14:57:16 2008 @@ -52,6 +52,28 @@ gctypelayout.zero_gc_pointers(result) return result + def malloc_resizable_buffer(self, TYPE, n): + typeid = self.get_type_id(TYPE) + addr = self.gc.malloc(typeid, n) + result = llmemory.cast_adr_to_ptr(addr, lltype.Ptr(TYPE)) + if not self.gc.malloc_zero_filled: + gctypelayout.zero_gc_pointers(result) + return result + + def resize_buffer(self, obj, new_size): + T = lltype.typeOf(obj).TO + buf = self.malloc_resizable_buffer(T, new_size) + # copy contents + arrayfld = T._arrayfld + new_arr = getattr(buf, arrayfld) + old_arr = getattr(obj, arrayfld) + for i in range(len(old_arr)): + new_arr[i] = old_arr[i] + return buf + + def finish_building_buffer(self, obj): + return obj + def free(self, TYPE, flavor='gc'): assert flavor != 'gc' return lltype.free(TYPE, flavor=flavor) Modified: pypy/branch/io-improvements/pypy/rpython/memory/test/test_gc.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/memory/test/test_gc.py (original) +++ pypy/branch/io-improvements/pypy/rpython/memory/test/test_gc.py Sun May 4 14:57:16 2008 @@ -429,6 +429,20 @@ assert self.interpret(func, []) == int(self.GC_CAN_MOVE) + def test_raw_array(self): + from pypy.rpython.lltypesystem.rstr import STR + from pypy.rpython.annlowlevel import hlstr + from pypy.rlib import rgc + + def f(): + ptr = rgc.raw_buffer_of_shape(STR, 1) + ptr.chars[0] = 'a' + ptr = rgc.resize_buffer(ptr, 2) + ptr.chars[1] = 'b' + return len(hlstr(rgc.finish_building_buffer(ptr))) + + assert self.interpret(f, []) == 2 + class TestMarkSweepGC(GCTest): from pypy.rpython.memory.gc.marksweep import MarkSweepGC as GCClass From fijal at codespeak.net Sun May 4 15:02:06 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 4 May 2008 15:02:06 +0200 (CEST) Subject: [pypy-svn] r54402 - in pypy/branch/io-improvements/pypy/rlib: . test Message-ID: <20080504130206.17FE2169E7D@codespeak.net> Author: fijal Date: Sun May 4 15:02:05 2008 New Revision: 54402 Modified: pypy/branch/io-improvements/pypy/rlib/rgc.py pypy/branch/io-improvements/pypy/rlib/test/test_rgc.py Log: Name change Modified: pypy/branch/io-improvements/pypy/rlib/rgc.py ============================================================================== --- pypy/branch/io-improvements/pypy/rlib/rgc.py (original) +++ pypy/branch/io-improvements/pypy/rlib/rgc.py Sun May 4 15:02:05 2008 @@ -233,15 +233,15 @@ hop.exception_cannot_occur() return hop.genop(opname, vlist, resulttype = hop.r_result.lowleveltype) -def raw_buffer_of_shape(T, init_size): +def resizable_buffer_of_shape(T, init_size): """ Pre-allocates structure of type T (varsized) with possibility to reallocate it further by resize_buffer. """ from pypy.rpython.lltypesystem import lltype return lltype.malloc(T, init_size) -class RawBufferOfShapeEntry(ExtRegistryEntry): - _about_ = raw_buffer_of_shape +class ResizableBufferOfShapeEntry(ExtRegistryEntry): + _about_ = resizable_buffer_of_shape def compute_result_annotation(self, s_T, s_init_size): from pypy.annotation import model as annmodel @@ -260,7 +260,7 @@ resulttype=hop.r_result.lowleveltype) def resize_buffer(ptr, new_size): - """ Resize raw buffer returned by raw_buffer_of_shape to new size + """ Resize raw buffer returned by resizable_buffer_of_shape to new size """ from pypy.rpython.lltypesystem import lltype T = lltype.typeOf(ptr).TO @@ -293,7 +293,7 @@ resulttype=hop.r_result.lowleveltype) def finish_building_buffer(ptr): - """ Finish building raw_buffer returned by raw_buffer_of_shape + """ Finish building resizable buffer returned by resizable_buffer_of_shape """ return ptr Modified: pypy/branch/io-improvements/pypy/rlib/test/test_rgc.py ============================================================================== --- pypy/branch/io-improvements/pypy/rlib/test/test_rgc.py (original) +++ pypy/branch/io-improvements/pypy/rlib/test/test_rgc.py Sun May 4 15:02:05 2008 @@ -37,12 +37,12 @@ assert res == True -def test_raw_array(): +def test_resizable_buffer(): from pypy.rpython.lltypesystem.rstr import STR from pypy.rpython.annlowlevel import hlstr def f(): - ptr = rgc.raw_buffer_of_shape(STR, 1) + ptr = rgc.resizable_buffer_of_shape(STR, 1) ptr.chars[0] = 'a' ptr = rgc.resize_buffer(ptr, 2) ptr.chars[1] = 'b' From fijal at codespeak.net Sun May 4 15:02:55 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 4 May 2008 15:02:55 +0200 (CEST) Subject: [pypy-svn] r54403 - pypy/branch/io-improvements/pypy/rpython/memory/test Message-ID: <20080504130255.E5FD0169E7E@codespeak.net> Author: fijal Date: Sun May 4 15:02:55 2008 New Revision: 54403 Modified: pypy/branch/io-improvements/pypy/rpython/memory/test/test_gc.py Log: Rename Modified: pypy/branch/io-improvements/pypy/rpython/memory/test/test_gc.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/memory/test/test_gc.py (original) +++ pypy/branch/io-improvements/pypy/rpython/memory/test/test_gc.py Sun May 4 15:02:55 2008 @@ -429,13 +429,13 @@ assert self.interpret(func, []) == int(self.GC_CAN_MOVE) - def test_raw_array(self): + def test_resizable_buffer(self): from pypy.rpython.lltypesystem.rstr import STR from pypy.rpython.annlowlevel import hlstr from pypy.rlib import rgc def f(): - ptr = rgc.raw_buffer_of_shape(STR, 1) + ptr = rgc.resizable_buffer_of_shape(STR, 1) ptr.chars[0] = 'a' ptr = rgc.resize_buffer(ptr, 2) ptr.chars[1] = 'b' From fijal at codespeak.net Sun May 4 15:21:34 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 4 May 2008 15:21:34 +0200 (CEST) Subject: [pypy-svn] r54404 - pypy/branch/io-improvements/pypy/rlib Message-ID: <20080504132134.93BAB169E7E@codespeak.net> Author: fijal Date: Sun May 4 15:21:34 2008 New Revision: 54404 Modified: pypy/branch/io-improvements/pypy/rlib/rgc.py Log: Few restrictions that simplify gc transformation Modified: pypy/branch/io-improvements/pypy/rlib/rgc.py ============================================================================== --- pypy/branch/io-improvements/pypy/rlib/rgc.py (original) +++ pypy/branch/io-improvements/pypy/rlib/rgc.py Sun May 4 15:21:34 2008 @@ -249,6 +249,8 @@ assert s_T.is_constant() assert isinstance(s_init_size, annmodel.SomeInteger) T = s_T.const + assert isinstance(T, lltype.Struct) + assert isinstance(getattr(T, T._arrayfld), lltype.Primitive) return annmodel.SomePtr(lltype.Ptr(T)) def specialize_call(self, hop): From fijal at codespeak.net Sun May 4 15:25:40 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 4 May 2008 15:25:40 +0200 (CEST) Subject: [pypy-svn] r54405 - pypy/branch/io-improvements/pypy/rlib Message-ID: <20080504132540.7CE32169E97@codespeak.net> Author: fijal Date: Sun May 4 15:25:40 2008 New Revision: 54405 Modified: pypy/branch/io-improvements/pypy/rlib/rgc.py Log: typo Modified: pypy/branch/io-improvements/pypy/rlib/rgc.py ============================================================================== --- pypy/branch/io-improvements/pypy/rlib/rgc.py (original) +++ pypy/branch/io-improvements/pypy/rlib/rgc.py Sun May 4 15:25:40 2008 @@ -249,8 +249,10 @@ assert s_T.is_constant() assert isinstance(s_init_size, annmodel.SomeInteger) T = s_T.const + # limit ourselves to structs and to a fact that var-sized element + # does not contain pointers. assert isinstance(T, lltype.Struct) - assert isinstance(getattr(T, T._arrayfld), lltype.Primitive) + assert isinstance(getattr(T, T._arrayfld).OF, lltype.Primitive) return annmodel.SomePtr(lltype.Ptr(T)) def specialize_call(self, hop): From cfbolz at codespeak.net Sun May 4 15:34:39 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sun, 4 May 2008 15:34:39 +0200 (CEST) Subject: [pypy-svn] r54406 - pypy/extradoc/sprintinfo/berlin-2008 Message-ID: <20080504133439.1D45C169EA0@codespeak.net> Author: cfbolz Date: Sun May 4 15:34:39 2008 New Revision: 54406 Added: pypy/extradoc/sprintinfo/berlin-2008/ pypy/extradoc/sprintinfo/berlin-2008/announcement.txt (contents, props changed) pypy/extradoc/sprintinfo/berlin-2008/people.txt (contents, props changed) Log: first draft of the sprint announcement Added: pypy/extradoc/sprintinfo/berlin-2008/announcement.txt ============================================================================== --- (empty file) +++ pypy/extradoc/sprintinfo/berlin-2008/announcement.txt Sun May 4 15:34:39 2008 @@ -0,0 +1,42 @@ +===================================================================== + PyPy Berlin Sprint (17-22nd May 2008) +===================================================================== + +The next PyPy sprint will be in the `c-base space station`_, Berlin, Germany, Earth. +Solar System. This is a fully public sprint: newcomers (from all planets) and +topics other than those proposed below are welcome. + +------------------------------ +Goals and topics of the sprint +------------------------------ + + - work on PyPy's assembler JIT backends + + - work on the SPy VM, PyPy's Squeak implementation, particularly the graphics + capabilities + + - work on PyPy's GameBoy emulator, which also needs graphics support + + - trying some large pure-Python applications or libraries on PyPy and fixing + the resulting bugs. Possibilities are Zope 3, Django and others. + +* We are open to all sorts of other tasks during the sprint, just + propose something. + +----------------------- +Location & Accomodation +----------------------- + +Please register by svn: + + http://codespeak.net/svn/pypy/extradoc/sprintinfo/berlin-2008/people.txt + +or on the pypy-sprint mailing list if you do not yet have check-in rights: + + http://codespeak.net/mailman/listinfo/pypy-sprint + + +----------- +Exact times +----------- + Added: pypy/extradoc/sprintinfo/berlin-2008/people.txt ============================================================================== --- (empty file) +++ pypy/extradoc/sprintinfo/berlin-2008/people.txt Sun May 4 15:34:39 2008 @@ -0,0 +1,54 @@ + +People coming to the Berlin sprint 2008 +======================================== + +People who have a ``?`` in their arrive/depart or accomodation +column are known to be coming but there are no details +available yet from them. + + +==================== ============== ======================= + Name Arrive/Depart Accomodation +==================== ============== ======================= +==================== ============== ======================= + +People on the following list were present at previous sprints: + +==================== ============== ===================== + Name Arrive/Depart Accomodation +==================== ============== ===================== +Christian Tismer ? ? +Michael Hudson ? ? +Anders Lehmann ? ? +Niklaus Haldimann ? ? +Lene Wagner ? ? +Amaury Forgeot d'Arc ? ? +Valentino Volonghi ? ? +Boris Feigin ? ? +Andrew Thompson ? ? +Bert Freudenberg ? ? +Beatrice Duering ? ? +Richard Emslie ? ? +Johan Hahn ? ? +Stephan Diehl ? ? +Niko Matsakis ? ? +Alexander Schremmer ? ? +Anders Chrigstroem ? ? +Samuele Pedroni ? ? +Michael Hudson ? ? +Niko Matsakis ? ? +Eric van Riet Paap ? ? +Jacob Hallen ? ? +Laura Creighton ? ? +Holger Krekel ? ? +Guido Wesdorp ? ? +Leonardo Santagada ? ? +Alexandre Fayolle ? ? +Sylvain Th?nault ? ? +Armin Rigo ? ? +Carl Friedrich Bolz ? ? +Antonio Cuni ? ? +Maciej Fijalkowski ? ? +Toby Watson ? ? +Paul deGrandis ? ? +==================== ============== ===================== From fijal at codespeak.net Sun May 4 15:36:56 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 4 May 2008 15:36:56 +0200 (CEST) Subject: [pypy-svn] r54407 - pypy/extradoc/sprintinfo/berlin-2008 Message-ID: <20080504133656.F0BF3169EA0@codespeak.net> Author: fijal Date: Sun May 4 15:36:53 2008 New Revision: 54407 Modified: pypy/extradoc/sprintinfo/berlin-2008/people.txt Log: add myself Modified: pypy/extradoc/sprintinfo/berlin-2008/people.txt ============================================================================== --- pypy/extradoc/sprintinfo/berlin-2008/people.txt (original) +++ pypy/extradoc/sprintinfo/berlin-2008/people.txt Sun May 4 15:36:53 2008 @@ -10,6 +10,7 @@ ==================== ============== ======================= Name Arrive/Depart Accomodation ==================== ============== ======================= +Maciej Fijalkowski 14-22.V private ==================== ============== ======================= People on the following list were present at previous sprints: @@ -48,7 +49,6 @@ Armin Rigo ? ? Carl Friedrich Bolz ? ? Antonio Cuni ? ? -Maciej Fijalkowski ? ? Toby Watson ? ? Paul deGrandis ? ? ==================== ============== ===================== From fijal at codespeak.net Sun May 4 16:34:56 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 4 May 2008 16:34:56 +0200 (CEST) Subject: [pypy-svn] r54408 - pypy/branch/io-improvements/pypy/rlib Message-ID: <20080504143456.EF925168541@codespeak.net> Author: fijal Date: Sun May 4 16:34:55 2008 New Revision: 54408 Modified: pypy/branch/io-improvements/pypy/rlib/rgc.py Log: make it look slightly more like normal malloc Modified: pypy/branch/io-improvements/pypy/rlib/rgc.py ============================================================================== --- pypy/branch/io-improvements/pypy/rlib/rgc.py (original) +++ pypy/branch/io-improvements/pypy/rlib/rgc.py Sun May 4 16:34:55 2008 @@ -257,7 +257,9 @@ def specialize_call(self, hop): from pypy.rpython.lltypesystem import lltype + flags = {'flavor': 'gc'} vlist = [hop.inputarg(lltype.Void, 0), + hop.inputconst(lltype.Void, flags), hop.inputarg(lltype.Signed, 1)] hop.exception_is_here() return hop.genop('malloc_resizable_buffer', vlist, From fijal at codespeak.net Sun May 4 16:35:48 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 4 May 2008 16:35:48 +0200 (CEST) Subject: [pypy-svn] r54409 - in pypy/branch/io-improvements/pypy/rpython/memory: gctransform test Message-ID: <20080504143548.3177D168541@codespeak.net> Author: fijal Date: Sun May 4 16:35:47 2008 New Revision: 54409 Modified: pypy/branch/io-improvements/pypy/rpython/memory/gctransform/transform.py pypy/branch/io-improvements/pypy/rpython/memory/test/test_transformed_gc.py Log: Start default transformation of resize_buffer. Modified: pypy/branch/io-improvements/pypy/rpython/memory/gctransform/transform.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/memory/gctransform/transform.py (original) +++ pypy/branch/io-improvements/pypy/rpython/memory/gctransform/transform.py Sun May 4 16:35:47 2008 @@ -522,6 +522,38 @@ gct_malloc_nonmovable = gct_malloc gct_malloc_nonmovable_varsize = gct_malloc_varsize + + gct_malloc_resizable_buffer = gct_malloc_varsize + + def gct_resize_buffer(self, hop): + op = hop.spaceop + meth = self.gct_fv_gc_malloc_varsize + flags = {'flavor':'gc'} + self.varsize_malloc_helper(hop, flags, meth, []) + # fish resvar + v_newbuf = hop.llops[-1].result + v_src = op.args[0] + TYPE = v_src.concretetype.TO + v_arr = hop.genop('getfield', [v_src, rmodel.inputconst(lltype.Void, + TYPE._arrayfld)], + resulttype=getattr(TYPE, TYPE._arrayfld)) + v_lgt = hop.genop('getfield', [v_arr, rmodel.inputconst(lltype.Void, + 'length')], + resulttype=lltype.Signed) + v_adrsrc = hop.genop('cast_ptr_to_adr', [v_src], + resulttype=llmemory.Address) + v_adrnewbuf = hop.genop('cast_ptr_to_adr', [v_newbuf], + resulttype=llmemory.Address) + ofs = (llmemory.offsetof(TYPE, TYPE._arrayfld) + + llmemory.itemoffsetof(getattr(TYPE, TYPE._arrayfld), 0)) + v_ofs = rmodel.inputconst(lltype.Void, ofs) + v_adrsrc = hop.genop('adr_add', [v_adrsrc, v_ofs], + resulttype=llmemory.Address) + v_adrnewbuf = hop.genop('adr_add', [v_adrnewbuf, v_ofs], + resulttype=llmemory.Address) + vlist = [v_adrsrc, v_adrnewbuf, v_lgt] + hop.genop('raw_memcopy', vlist) + return v_newbuf def varsize_malloc_helper(self, hop, flags, meth, extraargs): def intconst(c): return rmodel.inputconst(lltype.Signed, c) @@ -549,10 +581,8 @@ args = [hop] + extraargs + [flags, TYPE, op.args[-1], c_const_size, c_item_size, c_offset_to_length] v_raw = meth(*args) - hop.cast_result(v_raw) - def gct_fv_raw_malloc_varsize(self, hop, flags, TYPE, v_length, c_const_size, c_item_size, c_offset_to_length): if c_offset_to_length is None: Modified: pypy/branch/io-improvements/pypy/rpython/memory/test/test_transformed_gc.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/memory/test/test_transformed_gc.py (original) +++ pypy/branch/io-improvements/pypy/rpython/memory/test/test_transformed_gc.py Sun May 4 16:35:47 2008 @@ -492,17 +492,18 @@ run = self.runner(func) assert run([]) == int(self.GC_CAN_MOVE) - def test_raw_array(self): + def test_resizable_buffer(self): + py.test.skip("Does not work") from pypy.rpython.lltypesystem.rstr import STR from pypy.rpython.annlowlevel import hlstr from pypy.rlib import rgc def f(): - arr = rgc.raw_array_of_shape(STR, 1) - arr[0] = 'a' - arr = rgc.resize_raw_array(arr, 1, 2) - arr[1] = 'b' - return len(hlstr(rgc.cast_raw_array_to_shape(STR, arr, 2))) + ptr = rgc.resizable_buffer_of_shape(STR, 1) + ptr.chars[0] = 'a' + ptr = rgc.resize_buffer(ptr, 2) + ptr.chars[1] = 'b' + return len(hlstr(rgc.finish_building_buffer(ptr))) run = self.runner(f) assert run([]) == 2 From xoraxax at codespeak.net Sun May 4 16:43:10 2008 From: xoraxax at codespeak.net (xoraxax at codespeak.net) Date: Sun, 4 May 2008 16:43:10 +0200 (CEST) Subject: [pypy-svn] r54410 - in pypy/extradoc/talk: . xp2006 Message-ID: <20080504144310.1D73A16853B@codespeak.net> Author: xoraxax Date: Sun May 4 16:43:08 2008 New Revision: 54410 Added: pypy/extradoc/talk/xp2006/ pypy/extradoc/talk/xp2006/during-xp2006-sprints.pdf - copied unchanged from r54407, pypy/extradoc/talk/during-xp2006-sprints.pdf pypy/extradoc/talk/xp2006/proposal_pypy_agile2006.pdf - copied unchanged from r54407, pypy/extradoc/talk/proposal_pypy_agile2006.pdf pypy/extradoc/talk/xp2006/pypypaper_xp2006.sxw - copied unchanged from r54407, pypy/extradoc/talk/pypypaper_xp2006.sxw pypy/extradoc/talk/xp2006/pypypaper_xp2006_final.pdf - copied unchanged from r54407, pypy/extradoc/talk/pypypaper_xp2006_final.pdf pypy/extradoc/talk/xp2006/xp2006_pypypaper.pdf - copied unchanged from r54407, pypy/extradoc/talk/xp2006_pypypaper.pdf Removed: pypy/extradoc/talk/during-xp2006-sprints.pdf pypy/extradoc/talk/proposal_pypy_agile2006.pdf pypy/extradoc/talk/pypypaper_xp2006.sxw pypy/extradoc/talk/pypypaper_xp2006_final.pdf pypy/extradoc/talk/xp2006_pypypaper.pdf Log: Moved XP 2006 files into their own subdirectory. From xoraxax at codespeak.net Sun May 4 16:43:45 2008 From: xoraxax at codespeak.net (xoraxax at codespeak.net) Date: Sun, 4 May 2008 16:43:45 +0200 (CEST) Subject: [pypy-svn] r54411 - pypy/dist/pypy/doc Message-ID: <20080504144345.B6A6F168541@codespeak.net> Author: xoraxax Date: Sun May 4 16:43:44 2008 New Revision: 54411 Modified: pypy/dist/pypy/doc/extradoc.txt Log: Fix link to xp 2006 talk. Modified: pypy/dist/pypy/doc/extradoc.txt ============================================================================== --- pypy/dist/pypy/doc/extradoc.txt (original) +++ pypy/dist/pypy/doc/extradoc.txt Sun May 4 16:43:44 2008 @@ -89,7 +89,7 @@ .. _`py lib slides`: http://codespeak.net/pypy/extradoc/talk/2005-pycon-py.pdf .. _`PyCon 2005`: http://codespeak.net/pypy/extradoc/talk/pypy-talk-pycon2005/README.html .. _`Trouble in Paradise`: http://codespeak.net/pypy/extradoc/talk/agile2006/during-oss-sprints_talk.pdf -.. _`Sprint Driven Development`: http://codespeak.net/pypy/extradoc/talk/during-xp2006-sprints.pdf +.. _`Sprint Driven Development`: http://codespeak.net/pypy/extradoc/talk/xp2006/during-xp2006-sprints.pdf .. _`Kill -1`: http://codespeak.net/pypy/extradoc/talk/ep2006/kill_1_agiletalk.pdf .. _`Open Source, EU-Funding and Agile Methods`: http://codespeak.net/pypy/extradoc/talk/22c3/agility.pdf .. _`PyPy Status`: http://codespeak.net/pypy/extradoc/talk/vancouver/talk.html From cfbolz at codespeak.net Sun May 4 16:45:54 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sun, 4 May 2008 16:45:54 +0200 (CEST) Subject: [pypy-svn] r54412 - pypy/extradoc/sprintinfo/berlin-2008 Message-ID: <20080504144554.9CB901683E5@codespeak.net> Author: cfbolz Date: Sun May 4 16:45:53 2008 New Revision: 54412 Modified: pypy/extradoc/sprintinfo/berlin-2008/announcement.txt Log: more sprint announcement Modified: pypy/extradoc/sprintinfo/berlin-2008/announcement.txt ============================================================================== --- pypy/extradoc/sprintinfo/berlin-2008/announcement.txt (original) +++ pypy/extradoc/sprintinfo/berlin-2008/announcement.txt Sun May 4 16:45:53 2008 @@ -2,15 +2,19 @@ PyPy Berlin Sprint (17-22nd May 2008) ===================================================================== -The next PyPy sprint will be in the `c-base space station`_, Berlin, Germany, Earth. -Solar System. This is a fully public sprint: newcomers (from all planets) and -topics other than those proposed below are welcome. +The next PyPy sprint will be in the crashed `c-base space station`_, Berlin, +Germany, Earth. Solar System. This is a fully public sprint: newcomers (from +all planets) and topics other than those proposed below are welcome. + +.. _`c-base space station`: http://www.c-base.org/ + ------------------------------ Goals and topics of the sprint ------------------------------ - - work on PyPy's assembler JIT backends + - work on PyPy's JIT generator or the assembler backends (people with + knowledge of CPU details welcome) - work on the SPy VM, PyPy's Squeak implementation, particularly the graphics capabilities @@ -27,11 +31,23 @@ Location & Accomodation ----------------------- -Please register by svn: +The sprint will take place in the c-base in Berlin. The address is: + + c-base e.V. + Rungestrasse 20 + 10179 Berlin + +To get there, take the U-Bahn or S-Bahn to the station "Jannowitzbr?cke". See +here_ for a rough map to get from c-base from there. + +.. _here: http://www.c-base.org/cv50f/core/c-tour/htdocs/location.html + +If you want to come, please register via by svn: http://codespeak.net/svn/pypy/extradoc/sprintinfo/berlin-2008/people.txt -or on the pypy-sprint mailing list if you do not yet have check-in rights: +or write a mail to the pypy-sprint mailing list if you do not yet have check-in +rights: http://codespeak.net/mailman/listinfo/pypy-sprint @@ -40,3 +56,5 @@ Exact times ----------- +The sprint will be from 17th to 22nd of May 2008. We will start sprinting every +day at 10. An introduction will be given on the first day, if there is interest From arigo at codespeak.net Sun May 4 17:04:35 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 4 May 2008 17:04:35 +0200 (CEST) Subject: [pypy-svn] r54413 - pypy/extradoc/sprintinfo/berlin-2008 Message-ID: <20080504150435.4A7F8168556@codespeak.net> Author: arigo Date: Sun May 4 17:04:34 2008 New Revision: 54413 Modified: pypy/extradoc/sprintinfo/berlin-2008/announcement.txt Log: Fixes. Modified: pypy/extradoc/sprintinfo/berlin-2008/announcement.txt ============================================================================== --- pypy/extradoc/sprintinfo/berlin-2008/announcement.txt (original) +++ pypy/extradoc/sprintinfo/berlin-2008/announcement.txt Sun May 4 17:04:34 2008 @@ -3,7 +3,7 @@ ===================================================================== The next PyPy sprint will be in the crashed `c-base space station`_, Berlin, -Germany, Earth. Solar System. This is a fully public sprint: newcomers (from +Germany, Earth, Solar System. This is a fully public sprint: newcomers (from all planets) and topics other than those proposed below are welcome. .. _`c-base space station`: http://www.c-base.org/ @@ -13,8 +13,9 @@ Goals and topics of the sprint ------------------------------ - - work on PyPy's JIT generator or the assembler backends (people with - knowledge of CPU details welcome) + - work on PyPy's JIT generator: we are refactoring parts of the compiling + logic, in ways that may also allow generating better machine code for + loops (people with knowledge on compilers and SSA, welcome) - work on the SPy VM, PyPy's Squeak implementation, particularly the graphics capabilities @@ -31,14 +32,14 @@ Location & Accomodation ----------------------- -The sprint will take place in the c-base in Berlin. The address is: +The sprint will take place in the c-base in Berlin. The address is:: c-base e.V. Rungestrasse 20 10179 Berlin To get there, take the U-Bahn or S-Bahn to the station "Jannowitzbr?cke". See -here_ for a rough map to get from c-base from there. +here_ for a rough map to get to c-base from there. .. _here: http://www.c-base.org/cv50f/core/c-tour/htdocs/location.html @@ -51,10 +52,14 @@ http://codespeak.net/mailman/listinfo/pypy-sprint +Of course, especially given the location, it's ok to show up even if you +didn't register. (The c-base has probably got the plans of Guido's +famous time machine anyway, so you can register last week.) + ----------- Exact times ----------- The sprint will be from 17th to 22nd of May 2008. We will start sprinting every -day at 10. An introduction will be given on the first day, if there is interest +day at 10. An introduction will be given on the first day, if there is interest. From cfbolz at codespeak.net Sun May 4 17:20:11 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sun, 4 May 2008 17:20:11 +0200 (CEST) Subject: [pypy-svn] r54414 - pypy/extradoc/sprintinfo/berlin-2008 Message-ID: <20080504152011.EB65416855F@codespeak.net> Author: cfbolz Date: Sun May 4 17:20:11 2008 New Revision: 54414 Modified: pypy/extradoc/sprintinfo/berlin-2008/announcement.txt Log: reflow and different link Modified: pypy/extradoc/sprintinfo/berlin-2008/announcement.txt ============================================================================== --- pypy/extradoc/sprintinfo/berlin-2008/announcement.txt (original) +++ pypy/extradoc/sprintinfo/berlin-2008/announcement.txt Sun May 4 17:20:11 2008 @@ -2,9 +2,10 @@ PyPy Berlin Sprint (17-22nd May 2008) ===================================================================== -The next PyPy sprint will be in the crashed `c-base space station`_, Berlin, -Germany, Earth, Solar System. This is a fully public sprint: newcomers (from -all planets) and topics other than those proposed below are welcome. +The next PyPy sprint will be in the crashed `c-base space station`_, +Berlin, Germany, Earth, Solar System. This is a fully public sprint: +newcomers (from all planets) and topics other than those proposed below +are welcome. .. _`c-base space station`: http://www.c-base.org/ @@ -13,17 +14,19 @@ Goals and topics of the sprint ------------------------------ - - work on PyPy's JIT generator: we are refactoring parts of the compiling - logic, in ways that may also allow generating better machine code for - loops (people with knowledge on compilers and SSA, welcome) + - work on PyPy's JIT generator: we are refactoring parts of the + compiling logic, in ways that may also allow generating better + machine code for loops (people with knowledge on compilers and SSA, + welcome) - - work on the SPy VM, PyPy's Squeak implementation, particularly the graphics - capabilities + - work on the SPy VM, PyPy's Squeak implementation, particularly the + graphics capabilities - work on PyPy's GameBoy emulator, which also needs graphics support - - trying some large pure-Python applications or libraries on PyPy and fixing - the resulting bugs. Possibilities are Zope 3, Django and others. + - trying some large pure-Python applications or libraries on PyPy and + fixing the resulting bugs. Possibilities are Zope 3, Django and + others. * We are open to all sorts of other tasks during the sprint, just propose something. @@ -38,17 +41,17 @@ Rungestrasse 20 10179 Berlin -To get there, take the U-Bahn or S-Bahn to the station "Jannowitzbr?cke". See -here_ for a rough map to get to c-base from there. +To get there, take the U-Bahn or S-Bahn to the station +"Jannowitzbr?cke". See here_ for a map to get to c-base from there. -.. _here: http://www.c-base.org/cv50f/core/c-tour/htdocs/location.html +.. _here: http://maps.google.com/maps?f=q&hl=en&geocode=&q=c-base+berlin&ie=UTF8&ll=52.515464,13.408985&spn=0.020449,0.057335&z=15&iwloc=A If you want to come, please register via by svn: http://codespeak.net/svn/pypy/extradoc/sprintinfo/berlin-2008/people.txt -or write a mail to the pypy-sprint mailing list if you do not yet have check-in -rights: +or write a mail to the pypy-sprint mailing list if you do not yet have +check-in rights: http://codespeak.net/mailman/listinfo/pypy-sprint @@ -61,5 +64,6 @@ Exact times ----------- -The sprint will be from 17th to 22nd of May 2008. We will start sprinting every -day at 10. An introduction will be given on the first day, if there is interest. +The sprint will be from 17th to 22nd of May 2008. We will start +sprinting every day at 10. An introduction will be given on the first +day, if there is interest. From arigo at codespeak.net Sun May 4 17:23:21 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 4 May 2008 17:23:21 +0200 (CEST) Subject: [pypy-svn] r54415 - pypy/extradoc/sprintinfo/berlin-2008 Message-ID: <20080504152321.E3F6316857B@codespeak.net> Author: arigo Date: Sun May 4 17:23:21 2008 New Revision: 54415 Modified: pypy/extradoc/sprintinfo/berlin-2008/announcement.txt Log: this is a commit message. Modified: pypy/extradoc/sprintinfo/berlin-2008/announcement.txt ============================================================================== --- pypy/extradoc/sprintinfo/berlin-2008/announcement.txt (original) +++ pypy/extradoc/sprintinfo/berlin-2008/announcement.txt Sun May 4 17:23:21 2008 @@ -16,8 +16,8 @@ - work on PyPy's JIT generator: we are refactoring parts of the compiling logic, in ways that may also allow generating better - machine code for loops (people with knowledge on compilers and SSA, - welcome) + machine code for loops (people or aliens with knowledge on + compilers and SSA, welcome) - work on the SPy VM, PyPy's Squeak implementation, particularly the graphics capabilities From cfbolz at codespeak.net Sun May 4 17:44:23 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sun, 4 May 2008 17:44:23 +0200 (CEST) Subject: [pypy-svn] r54416 - pypy/extradoc/sprintinfo/berlin-2008 Message-ID: <20080504154423.663B62A8093@codespeak.net> Author: cfbolz Date: Sun May 4 17:44:21 2008 New Revision: 54416 Modified: pypy/extradoc/sprintinfo/berlin-2008/announcement.txt Log: use latin-1. ReST sucks! Modified: pypy/extradoc/sprintinfo/berlin-2008/announcement.txt ============================================================================== --- pypy/extradoc/sprintinfo/berlin-2008/announcement.txt (original) +++ pypy/extradoc/sprintinfo/berlin-2008/announcement.txt Sun May 4 17:44:21 2008 @@ -42,7 +42,7 @@ 10179 Berlin To get there, take the U-Bahn or S-Bahn to the station -"Jannowitzbr??cke". See here_ for a map to get to c-base from there. +"Jannowitzbr?cke". See here_ for a map to get to c-base from there. .. _here: http://maps.google.com/maps?f=q&hl=en&geocode=&q=c-base+berlin&ie=UTF8&ll=52.515464,13.408985&spn=0.020449,0.057335&z=15&iwloc=A From stephan at codespeak.net Sun May 4 17:48:52 2008 From: stephan at codespeak.net (stephan at codespeak.net) Date: Sun, 4 May 2008 17:48:52 +0200 (CEST) Subject: [pypy-svn] r54417 - pypy/extradoc/sprintinfo/berlin-2008 Message-ID: <20080504154852.DA9292A8092@codespeak.net> Author: stephan Date: Sun May 4 17:48:52 2008 New Revision: 54417 Modified: pypy/extradoc/sprintinfo/berlin-2008/people.txt Log: added myself Modified: pypy/extradoc/sprintinfo/berlin-2008/people.txt ============================================================================== --- pypy/extradoc/sprintinfo/berlin-2008/people.txt (original) +++ pypy/extradoc/sprintinfo/berlin-2008/people.txt Sun May 4 17:48:52 2008 @@ -11,6 +11,7 @@ Name Arrive/Depart Accomodation ==================== ============== ======================= Maciej Fijalkowski 14-22.V private +Stephan Diehl ? private ==================== ============== ======================= People on the following list were present at previous sprints: @@ -31,7 +32,6 @@ Beatrice Duering ? ? Richard Emslie ? ? Johan Hahn ? ? -Stephan Diehl ? ? Niko Matsakis ? ? Alexander Schremmer ? ? Anders Chrigstroem ? ? From cami at codespeak.net Sun May 4 22:55:18 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Sun, 4 May 2008 22:55:18 +0200 (CEST) Subject: [pypy-svn] r54422 - in pypy/branch/gameboy-emulator/pypy/lang/gameboy: . test Message-ID: <20080504205518.D65F62A807D@codespeak.net> Author: cami Date: Sun May 4 22:55:17 2008 New Revision: 54422 Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cpu.py Log: finished cpu testing fixed some bugs in the fetch execute opCodes Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py Sun May 4 22:55:17 2008 @@ -311,10 +311,10 @@ def isNotN(self): return not self.isN() - - # Flags ............................................ - + def setROM(self, banks): + + # Flags ............................................ self.rom = banks def emulate(self, ticks): @@ -323,8 +323,8 @@ while self.cycles > 0: self.execute(self.fetch()) - # Interrupts def handlePendingInterrupt(self): + # Interrupts if self.halted: if self.interrupt.isPending(): self.halted = False @@ -342,28 +342,28 @@ flag.setPending(False) return - # Execution def fetchExecute(self): + # Execution FETCH_EXECUTE_OP_CODES[self.fetch()](self) def execute(self, opCode): OP_CODES[opCode](self) - # memory Access, 1 cycle def read(self, hi, lo=None): + # memory Access, 1 cycle address = hi if lo != None: address = (hi << 8) + lo self.cycles -= 1 return self.memory.read(address) - # 2 cycles def write(self, address, data): + # 2 cycles self.memory.write(address, data) self.cycles -= 2 - # Fetching 1 cycle def fetch(self, useCycles=True): + # Fetching 1 cycle self.cycles += 1 if self.pc.get(useCycles) <= 0x3FFF: data = self.rom[self.pc.get(useCycles)] @@ -380,25 +380,25 @@ def fetchDoubleRegister(self, register): self.popDoubleRegister(CPU.fetch, register) - # Stack, 2 cycles def push(self, data, useCycles=True): + # Stack, 2 cycles self.sp.dec(useCycles) # 2 cycles self.memory.write(self.sp.get(useCycles), data) - # PUSH rr 4 cycles def pushDoubleRegister(self, register, useCycles=True): + # PUSH rr 4 cycles self.push(register.getHi(), useCycles) # 2 cycles self.push(register.getLo(), useCycles) # 2 cycles - # 1 cycle def pop(self): + # 1 cycle data = self.memory.read(self.sp.get()) self.sp.inc() # 2 cycles self.cycles += 1 return data - # 3 cycles def popDoubleRegister(self, getter, register=None): + # 3 cycles if register == None: register = getter getter = CPU.pop @@ -407,38 +407,38 @@ register.set(a, b) # 2 cycles self.cycles += 1 - # 4 cycles def call(self, address, useCycles=True): + # 4 cycles self.push(self.pc.getHi(useCycles), useCycles) # 2 cycles self.push(self.pc.getLo(useCycles), useCycles) # 2 cycles self.pc.set(address, None, useCycles) # 1 cycle if useCycles: self.cycles += 1 - # 1 cycle def ld(self, getter, setter): + # 1 cycle setter(getter()) # 1 cycle def loadFetchRegister(self, register): self.ld(self.fetch, register.set) - # LD PC,HL, 1 cycle def storeHlInPC(self): + # LD PC,HL, 1 cycle self.ld(self.hl.get, self.pc.set) def fetchLoad(self, getter, setter): self.ld(self.fetch, setter) - # ALU, 1 cycle def addA(self, getter, setter=None): + # ALU, 1 cycle added = (self.a.get() + getter()) & 0xFF self.f.zFlagCompare(added, reset=True) self.f.hFlagCompare(added, self.a) self.f.cFlagCompare(added, self.a) self.a.set(added) # 1 cycle - # 2 cycles def addHL(self, register): + # 2 cycles added = (self.hl.get() + register.get()) & 0xFFFF # 1 cycle self.f.reset(keepZ=True) self.f.hFlagCompare((added >> 8), self.hl) @@ -446,16 +446,16 @@ self.hl.set(added) self.cycles -= 1 - # 1 cycle def addWithCarry(self, getter, setter=None): + # 1 cycle data = getter() s = self.a.get() + data if self.f.cFlag: s +=1 self.carryFlagFinish(s,data) - # 1 cycle def subtractWithCarry(self, getter, setter=None): + # 1 cycle data = getter() s = self.a.get() - data if self.f.cFlag: @@ -473,8 +473,8 @@ self.f.zFlagCompare(s) self.a.set(s) # 1 cycle - # 1 cycle def subtractA(self, getter, setter=None): + # 1 cycle self.compareA(getter, setter) # 1 cycle self.a.sub(getter(useCycles=False), False) @@ -482,8 +482,8 @@ data = self.fetch() self.subtractA(lambda useCycles=False: data) - # 1 cycle def compareA(self, getter, setter=None): + # 1 cycle s = (self.a.get() - getter()) & 0xFF self.f.reset() self.f.nFlag = True @@ -496,18 +496,18 @@ self.f.cFlag = True self.f.hFlagCompare(self.a, data) - # 1 cycle def AND(self, getter, setter=None): + # 1 cycle self.a.set(self.a.get() & getter()) # 1 cycle self.f.zFlagCompare(self.a, reset=True) - # 1 cycle def XOR(self, getter, setter=None): + # 1 cycle self.a.set( self.a.get() ^ getter()) # 1 cycle self.f.zFlagCompare(self.a, reset=True) - # 1 cycle def OR(self, getter, setter=None): + # 1 cycle self.a.set(self.a.get() | getter()) # 1 cycle self.f.zFlagCompare(self.a, reset=True) @@ -517,13 +517,13 @@ def decDoubleRegister(self, doubleRegister): doubleRegister.dec() - # 1 cycle def inc(self, getter, setter): + # 1 cycle data = (getter() + 1) & 0xFF self.decIncFlagFinish(data, setter, 0x00) - # 1 cycle def dec(self, getter, setter): + # 1 cycle data = (getter() - 1) & 0xFF self.decIncFlagFinish(data, setter, 0x0F) self.f.nFlag = True @@ -535,98 +535,104 @@ self.f.hFlag = True setter(data) # 1 cycle - # RLC 1 cycle def rotateLeftCircular(self, getter, setter): + print "rotateLeftCircular", setter, self.cycles + # RLC 1 cycle data = getter() s = (data << 1) + (data >> 7) self.flagsAndSetterFinish(s, setter, 0x80) + print self.cycles + #self.cycles -= 1 - # RLCA rotateLeftCircularA 1 cycle def rotateLeftCircularA(self): + # RLCA rotateLeftCircularA 1 cycle self.rotateLeftCircular(self.a.get, self.a.set) - # 1 cycle def rotateLeft(self, getter, setter): - s = ((getter() & 0x7F) << 1) + # 1 cycle + s = (getter() << 1) & 0xFF if self.f.cFlag: s += 0x01 self.flagsAndSetterFinish(s, setter, 0x80) # 1 cycle - # RLA 1 cycle def rotateLeftA(self): + # RLA 1 cycle self.rotateLeft(self.a.get, self.a.set) - # RRC 1 cycle def rotateRightCircular(self, getter, setter): - s = (getter() >> 1) + (getter() << 7) + data = getter() + # RRC 1 cycle + s = (data >> 1) + ((data & 0x01) << 7) self.flagsAndSetterFinish(s, setter) # 1 cycle - # RRCA 1 cycle def rotateRightCircularA(self): + # RRCA 1 cycle self.rotateRightCircular(self.a.get, self.a.set) - # 1 cycle def rotateRight(self, getter, setter): + # 1 cycle s = (getter() >> 1) if self.f.cFlag: s += 0x08 self.flagsAndSetterFinish(s, setter) # 1 cycle - # RRA 1 cycle def rotateRightA(self): + # RRA 1 cycle self.rotateRight(self.a.get, self.a.set) - # 2 cycles def shiftLeftArithmetic(self, getter, setter): + # 2 cycles s = (getter() << 1) & 0xFF self.flagsAndSetterFinish(s, setter, 0x80) # 1 cycle - # 1 cycle def shiftRightArithmetic(self, getter, setter): - s = (getter() >> 1) + (getter() & 0x80) + data = getter() + # 1 cycle + s = (data >> 1) + (data & 0x80) self.flagsAndSetterFinish(s, setter) # 1 cycle - # 2 cycles def shiftWordRightLogical(self, getter, setter): + # 2 cycles s = (getter() >> 1) self.flagsAndSetterFinish(s, setter) # 2 cycles - # 2 cycles def flagsAndSetterFinish(self, s, setter, compareAnd=0x01): + # 2 cycles s &= 0xFF self.f.zFlagCompare(s, reset=True) self.f.cFlagAdd(s, compareAnd) setter(s) # 1 cycle - # 1 cycle def swap(self, getter, setter): - s = ((getter() << 4) + (getter() >> 4)) & 0xFF + data = getter() + # 1 cycle + s = ((data << 4) + (data >> 4)) & 0xFF self.f.zFlagCompare(s, reset=True) setter(s) - # 2 cycles def testBit(self, getter, setter, n): + # 2 cycles self.f.reset(keepC=True) self.f.hFlag = True + self.f.zFlag = False if (getter() & (1 << n)) == 0: self.f.zFlag = True - self.cycles -= 2 + self.cycles -= 1 - # 2 cycles def setBit(self, getter, setter, n): - self.cycles -= 1 # 1 cycle + # 1 cycle setter(getter() | (1 << n)) # 1 cycle - # 1 cycle def resetBit(self, getter, setter, n): + # 1 cycle setter(getter() & (~(1 << n))) # 1 cycle - # LD A,(nnnn), 4 cycles def storeFetchedMemoryInA(self): + # LD A,(nnnn), 4 cycles self.a.set(self.read(self.fetchDoubleAddress())) # 1+1 + 2 cycles - # 2 cycles def writeAAtBCAddress(self): + # 2 cycles self.write(self.bc.get(), self.a.get()) def writeAAtDEAddress(self): @@ -638,74 +644,74 @@ def storeMemoryAtDEInA(self): self.a.set(self.read(self.de.get())) - # LD (rr),A 2 cycles def ld_dbRegisteri_A(self, register): + # LD (rr),A 2 cycles self.write(register.get(), self.a.get()) # 2 cycles - # LD (nnnn),SP 5 cycles def load_mem_SP(self): + # LD (nnnn),SP 5 cycles address = self.fetchDoubleAddress() # 2 cycles self.write(address, self.sp.getLo()) # 2 cycles self.write((address + 1), self.sp.getHi()) # 2 cycles self.cycles += 1 - # LD (nnnn),A 4 cycles def storeAAtFetchedAddress(self): + # LD (nnnn),A 4 cycles self.write(self.fetchDoubleAddress(), self.a.get()) # 2 cycles - # LDH A,(nn) 3 cycles def storeMemoryAtExpandedFetchAddressInA(self): + # LDH A,(nn) 3 cycles self.a.set(self.read(0xFF00 + self.fetch())) # 1+1+1 cycles - # LDH A,(C) 2 cycles def storeExpandedCinA(self): + # LDH A,(C) 2 cycles self.a.set(self.read(0xFF00 + self.bc.getLo())) # 1+2 cycles - # loadAndIncrement A,(HL) 2 cycles def loadAndIncrement_A_HLi(self): + # loadAndIncrement A,(HL) 2 cycles self.a.set(self.read(self.hl.get())) # 2 cycles self.hl.inc()# 2 cycles self.cycles += 2 - # loadAndDecrement A,(HL) 2 cycles def loadAndDecrement_A_HLi(self): + # loadAndDecrement A,(HL) 2 cycles self.a.set(self.read(self.hl.get())) # 2 cycles self.hl.dec() # 2 cycles self.cycles += 2 - # LDH (nn),A 3 cycles def writeAatExpandedFetchAddress(self): + # LDH (nn),A 3 cycles self.write(0xFF00 + self.fetch(), self.a.get()) # 2 + 1 cycles - # LDH (C),A 2 cycles def writeAAtExpandedCAddress(self): + # LDH (C),A 2 cycles self.write(0xFF00 + self.bc.getLo(), self.a.get()) # 2 cycles - # loadAndIncrement (HL),A 2 cycles def loadAndIncrement_HLi_A(self): + # loadAndIncrement (HL),A 2 cycles self.write(self.hl.get(), self.a.get()) # 2 cycles self.hl.inc() # 2 cycles self.cycles += 2 - # loadAndDecrement (HL),A 2 cycles def loadAndDecrement_HLi_A(self): + # loadAndDecrement (HL),A 2 cycles self.write(self.hl.get(), self.a.get()) # 2 cycles self.hl.dec() # 2 cycles self.cycles += 2 - # LD SP,HL 2 cycles def storeHlInSp(self): + # LD SP,HL 2 cycles self.sp.set(self.hl.get()) # 1 cycle self.cycles -= 1 - # CPA def complementA(self): + # CPA self.a.set(self.a.get() ^ 0xFF) self.f.nFlag = True self.f.hFlag = True - # DAA 1 cycle def decimalAdjustAccumulator(self): + # DAA 1 cycle delta = 0 if self.isH(): delta |= 0x06 @@ -726,26 +732,26 @@ self.f.cFlag = True self.f.zFlagCompare(self.a) - # INC rr def incDoubleRegister(self, register): + # INC rr register.inc() - # DEC rr def decDoubleRegister(self, register): + # DEC rr register.dec() - # ADD SP,nn 4 cycles def incrementSPByFetch(self): + # ADD SP,nn 4 cycles self.sp.set(self.getFetchAddedSP()) # 1+1 cycle self.cycles -= 2 - # LD HL,SP+nn 3 cycles def storeFetchAddedSPInHL(self): + # LD HL,SP+nn 3 cycles self.hl.set(self.getFetchAddedSP()) # 1+1 cycle self.cycles -= 1 - # 1 cycle def getFetchAddedSP(self): + # 1 cycle offset = self.fetch() # 1 cycle s = (self.sp.get() + offset) & 0xFFFF self.f.reset() @@ -761,8 +767,8 @@ self.f.hFlag = True return s - # CCF/SCF def complementCarryFlag(self): + # CCF/SCF self.f.reset(keepZ=True, keepC=True) self.f.cFlag = not self.f.cFlag @@ -770,53 +776,53 @@ self.f.reset(keepZ=True) self.f.cFlag = True - # NOP 1 cycle def nop(self): + # NOP 1 cycle self.cycles -= 1 - # JP nnnn, 4 cycles def unconditionalJump(self): + # JP nnnn, 4 cycles self.pc.set(self.fetchDoubleAddress()) # 1+2 cycles self.cycles -= 1 - # JP cc,nnnn 3,4 cycles def conditionalJump(self, cc): + # JP cc,nnnn 3,4 cycles if cc: self.unconditionalJump() # 4 cycles else: self.pc.add(2) # 3 cycles - # JR +nn, 3 cycles def relativeUnconditionalJump(self): + # JR +nn, 3 cycles self.pc.add(self.fetch()) # 3 + 1 cycles self.cycles += 1 - # JR cc,+nn, 2,3 cycles def relativeConditionalJump(self, cc): + # JR cc,+nn, 2,3 cycles if cc: self.relativeUnconditionalJump() # 3 cycles else: self.pc.inc() # 2 cycles - # CALL nnnn, 6 cycles def unconditionalCall(self): + # CALL nnnn, 6 cycles self.call(self.fetchDoubleAddress()) # 4+2 cycles - # CALL cc,nnnn, 3,6 cycles def conditionalCall(self, cc): + # CALL cc,nnnn, 3,6 cycles if cc: self.unconditionalCall() # 6 cycles else: self.pc.add(2) # 3 cycles - # RET 4 cycles def ret(self): + # RET 4 cycles lo = self.pop() # 1 cycle hi = self.pop() # 1 cycle self.pc.set(hi, lo) # 2 cycles - # RET cc 2,5 cycles def conditionalReturn(self, cc): + # RET cc 2,5 cycles if cc: self.ret() # 4 cycles # FIXME maybe this should be the same @@ -824,54 +830,65 @@ else: self.cycles -= 2 - # RETI 4 cycles def returnFormInterrupt(self): + # RETI 4 cycles self.ret() # 4 cycles self.enableInterrupts() # 1 cycle + others self.cycles += 1 - # RST nn 4 cycles def restart(self, nn): + # RST nn 4 cycles self.call(nn) # 4 cycles - # DI/EI 1 cycle def disableInterrupts(self): + # DI/EI 1 cycle self.ime = False self.cycles -= 1 - # 1 cycle def enableInterrupts(self): + # 1 cycle self.ime = True self.execute(self.fetch()) # 1 self.handlePendingInterrupt() - # HALT/STOP def halt(self): + # HALT/STOP self.halted = True # emulate bug when interrupts are pending if (not self.ime and self.interrupt.isPending()): self.execute(self.memory.read(self.pc.get())) self.handlePendingInterrupt() - # 0 cycles def stop(self): + # 0 cycles self.cycles += 1 self.fetch() +# ------------------------------------------------------------------------------ # OPCODE LOOKUP TABLE GENERATION ----------------------------------------------- + GROUPED_REGISTERS = (CPU.getB, CPU.getC, CPU.getD, CPU.getE, CPU.getH, CPU.getL, CPU.getHLi, CPU.getA) + def create_group_op_codes(table): opCodes =[] for entry in table: - opCode = entry[0] - step = entry[1] + opCode = entry[0] + step = entry[1] function = entry[2] if len(entry) == 4: for registerGetter in GROUPED_REGISTERS: for n in entry[3]: opCodes.append((opCode, group_lambda(function, registerGetter, n))) opCode += step + if len(entry) == 5: + entryStep = entry[4] + for registerGetter in GROUPED_REGISTERS: + stepOpCode = opCode + for n in entry[3]: + opCodes.append((stepOpCode, group_lambda(function, registerGetter, n))) + stepOpCode += entryStep + opCode+=step else: for registerGetter in GROUPED_REGISTERS: opCodes.append((opCode,group_lambda(function, registerGetter))) @@ -884,9 +901,10 @@ else: return lambda s: function(s, registerGetter(s).get, registerGetter(s).set, value) + def create_load_group_op_codes(): opCodes = [] - opCode = 0x40 + opCode = 0x40 for storeRegister in GROUPED_REGISTERS: for loadRegister in GROUPED_REGISTERS: if loadRegister != CPU.getHLi or storeRegister != CPU.getHLi: @@ -897,6 +915,7 @@ def load_group_lambda(storeRegister, loadRegister): return lambda s: CPU.ld(s, loadRegister(s).get, storeRegister(s).set) + def create_register_op_codes(table): opCodes = [] for entry in table: @@ -914,6 +933,7 @@ else: return lambda s: function(s, registerOrGetter) + def initialize_op_code_table(table): result = [None] * (0xFF+1) for entry in table: @@ -1027,9 +1047,9 @@ (0x28, 0x01, CPU.shiftRightArithmetic), (0x30, 0x01, CPU.swap), (0x38, 0x01, CPU.shiftWordRightLogical), - (0x40, 0x01, CPU.testBit, range(0, 8)), - (0xC0, 0x01, CPU.setBit, range(0, 8)), - (0x80, 0x01, CPU.resetBit, range(0, 8)) + (0x40, 0x01, CPU.testBit, range(0, 8), 0x08), + (0xC0, 0x01, CPU.setBit, range(0, 8), 0x08), + (0x80, 0x01, CPU.resetBit, range(0, 8), 0x08) ] # RAW OPCODE TABLE INITIALIZATION ---------------------------------------------- Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cpu.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cpu.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cpu.py Sun May 4 22:55:17 2008 @@ -28,7 +28,7 @@ TEST_CPU.reset() return TEST_CPU -# ------------------------------------------------------------ +# ------------------------------------------------------------------------------ # TEST CPU @@ -140,21 +140,27 @@ prepare_for_fetch(cpu, opCode) cycle_test(cpu, 0xCB, cycles) -def cycle_test(cpu, opCode, cycles=0): +def cycle_test(cpu, opCode, cycles=0, opCodeDisplay=None): + if opCodeDisplay==None: + opCodeDisplay = hex(opCode) startCycles = cpu.cycles try: cpu.execute(opCode) except Exception, inst: - assert False, "Opcode %s %s failed to execute: %s" % (hex(opCode), OP_CODES[opCode], inst) + assert False, "Opcode %s %s failed to execute: %s" % (opCodeDisplay, OP_CODES[opCode], inst) cpuUsedCycles = startCycles-cpu.cycles assert cpuUsedCycles == cycles,\ "Cycles for opCode %s [CPU.%s] should be %i not %i" %\ - (hex(opCode).ljust(2),\ + ((opCodeDisplay).ljust(2),\ OP_CODES[opCode],\ cycles, cpuUsedCycles) -# TEST HELPERS --------------------------------------- +def fetch_execute_cycle_test_second_order(cpu, opCode, cycles=0): + prepare_for_fetch(cpu, opCode) + cycle_test(cpu, 0xCB, cycles, "[0xCB -> "+hex(opCode)+"]") + +# TEST HELPERS ----------------------------------------------------------------- def test_create_group_op_codes(): assert len(GROUPED_REGISTERS) == 8 @@ -268,7 +274,7 @@ register.set(value); -# test helper methods --------------------------------------------------------- +# test helper methods ---------------------------------------------------------- def test_prepare_for_pop(): cpu = get_cpu() @@ -284,7 +290,7 @@ assert cpu.fetch() == value+1 assert cpu.fetch() == value -# ------------------------------------------------------------ +# ------------------------------------------------------------------------------ # opCode Testing #nop @@ -1522,7 +1528,12 @@ # switching to other opcode set def test_0xCB(): - pass + cpu = get_cpu() + pc = cpu.pc.get() + prepare_for_fetch(cpu, 0x80) + cycle_test(cpu, 0xCB, 2) + assert_default_registers(cpu, pc=pc+1) + def test_rotateLeftCircular_flags(): cpu = get_cpu() @@ -1538,70 +1549,128 @@ assert_default_flags(cpu, zFlag=False, cFlag=True) assert_default_registers(cpu, a=0x80, f=None) -# rlc_B to rlc_A -def test_0x00_to_0x07_rotateLeftCircular(): + +# SECOND ORDER OPCODES --------------------------------------------------------- + +def second_order_test(opCode, createFunction): cpu = get_cpu() registers = [cpu.b, cpu.c, cpu.d, cpu.e, cpu.h, cpu.l, cpu.hli, cpu.a] - opCode = 0x00 - value = 0x12 + value = 0xF0 for register in registers: cpu.reset() register.set(value) cycles = 2 if register == cpu.hli: cycles = 4 - fetch_execute_cycle_test(cpu, opCode, cycles) - rlc = ((value & 0x7F) << 1) + ((value & 0x80) >> 7) - assert register.get() == rlc + fetch_execute_cycle_test_second_order(cpu, opCode, cycles) + assert register.get() == createFunction(value) opCode += 0x01 value += 1 +# rlc_B to rlc_A +def test_0x00_to_0x07_rotateLeftCircular(): + second_order_test(0x00, lambda value:((value & 0x7F) << 1) + ((value & 0x80) >> 7)) + # rrc_B to rrc_F -def test_0x08_to_0x0F(): - cpu = get_cpu() - opCode = 0x38 +def test_0x08_to_0x0F_rotateRightCircular(): + second_order_test(0x08, lambda value:(value >> 1) + ((value & 0x01) << 7)) # rl_B to rl_A -def test_0x10_to_0x17(): - cpu = get_cpu() - opCode = 0x38 +def test_0x10_to_0x17_shift_left(): + second_order_test(0x10, lambda value: (value << 1) & 0xFF ) # rr_B to rr_A -def test_0x18_to_0x1F(): - cpu = get_cpu() - opCode = 0x38 +def test_0x18_to_0x1F_shift_right(): + second_order_test(0x18, lambda value: value >> 1) # sla_B to sla_A -def test_0x20_to_0x27(): - cpu = get_cpu() - opCode = 0x38 +def test_0x20_to_0x27_shift_left_arithmetic(): + second_order_test(0x20, lambda value: (value << 1) & 0xFF) # sra_B to sra_A -def test_0x28_to_0x2F(): - cpu = get_cpu() - opCode = 0x38 +def test_0x28_to_0x2F_shift_right_arithmetic(): + second_order_test(0x28, lambda value: (value >> 1) + (value & 0x80)) # swap_B to swap_A def test_0x30_to_0x37(): - cpu = get_cpu() - opCode = 0x38 + second_order_test(0x30, lambda value: ((value << 4) + (value >> 4)) & 0xFF) # srl_B to srl_A -def test_0x38_to_0x3F(): - cpu = get_cpu() - opCode = 0x38 +def test_0x38_to_0x3F_shift_word_right_logical(): + second_order_test(0x38, lambda value: value >> 1) # bit_B to bit_A -def test_bit_opCodes(): +def test_testBit_opCodes(): + cpu = get_cpu() + registers = [cpu.b, cpu.c, cpu.d, cpu.e, cpu.h, cpu.l, cpu.hli, cpu.a] opCode = 0x40 + for register in registers: + registerOpCode = opCode + for i in range(8): + cycles = 2 + if register == cpu.hli: + cycles = 3 + + cpu.reset() + register.set(0) + fetch_execute_cycle_test_second_order(cpu, registerOpCode, cycles) + assert cpu.f.zFlag == True + + cpu.reset() + register.set((1<> i == 1 + fetch_execute_cycle_test_second_order(cpu, registerOpCode, cycles) + assert (register.get() & (1<> i == 1 + registerOpCode += 0x08 + opCode += 0x01 # res_B to res_A -def test_res_opCodes(): +def test_resetBit_opCodes(): + cpu = get_cpu() + registers = [cpu.b, cpu.c, cpu.d, cpu.e, cpu.h, cpu.l, cpu.hli, cpu.a] + value = 0x12 opCode = 0x80 + for register in registers: + registerOpCode = opCode + cycles = 2 + if register == cpu.hli: + cycles = 4 + + for i in range(8): + cpu.reset() + register.set(0) + fetch_execute_cycle_test_second_order(cpu, registerOpCode, cycles) + assert (register.get() & (1< Author: cami Date: Sun May 4 22:56:07 2008 New Revision: 54423 Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cpu.py Log: removed an unused "pass" Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cpu.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cpu.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cpu.py Sun May 4 22:56:07 2008 @@ -1524,7 +1524,6 @@ assert cpu.pc.get() == rstValue opCode += 0x08 rstValue += 0x08 - pass # switching to other opcode set def test_0xCB(): From cami at codespeak.net Sun May 4 22:57:44 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Sun, 4 May 2008 22:57:44 +0200 (CEST) Subject: [pypy-svn] r54424 - pypy/branch/gameboy-emulator/pypy/lang/gameboy/test Message-ID: <20080504205744.4AF092A807D@codespeak.net> Author: cami Date: Sun May 4 22:57:43 2008 New Revision: 54424 Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_rom.py Log: skipped test for rom4 due to problems with the resteBit function Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_rom.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_rom.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_rom.py Sun May 4 22:57:43 2008 @@ -38,6 +38,7 @@ def test_rom4(): + py.test.skip("problem with resetBit") gameBoy = GameBoy() gameBoy.loadCartridgeFile(ROM_PATH+"/rom4/rom4.gb") gameBoy.emulate(EMULATION_CYCLES) From cami at codespeak.net Sun May 4 23:37:55 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Sun, 4 May 2008 23:37:55 +0200 (CEST) Subject: [pypy-svn] r54425 - in pypy/branch/gameboy-emulator/pypy/lang/gameboy: . test Message-ID: <20080504213755.A36A416856E@codespeak.net> Author: cami Date: Sun May 4 23:37:53 2008 New Revision: 54425 Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboy.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/joypad.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_rom.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/video.py Log: completed rom tests gameboy: fixed a nasty do-nothing-return-bug in GameBoy.read joypad: removed the needless ( in the if statemends video: fixed a broken function call cpu: removed debug print statements cartridge: fixed an unfinished variable access Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py Sun May 4 23:37:53 2008 @@ -250,7 +250,8 @@ if address <= 0x3FFF: # 0000-3FFF return self.rom[address] & 0xFF elif address <= 0x7FFF:# 4000-7FFF - return self.rom[romBank + (address & 0x3FFF)] & 0xFF + print address, self.romBank + return self.rom[self.romBank + (address & 0x3FFF)] & 0xFF elif address >= 0xA000 and address <= 0xBFFF and self.ramEnable: # A000-BFFF return self.ram[self.ramBank + (address & 0x1FFF)] & 0xFF return 0xFF Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py Sun May 4 23:37:53 2008 @@ -187,7 +187,11 @@ self.ime = False self.halted = False self.cycles = 0 - + self.iniRegisters() + self.rom = [] + self.reset() + + def iniRegisters(self): self.b = Register(self) self.c = Register(self) self.bc = DoubleRegister(self, self.b, self.c, constants.RESET_BC) @@ -208,8 +212,6 @@ self.f = FlagRegister(self) self.af = DoubleRegister(self, self.a, self.f) - self.rom = [] - self.reset() def reset(self): self.resetRegisters() @@ -536,12 +538,10 @@ setter(data) # 1 cycle def rotateLeftCircular(self, getter, setter): - print "rotateLeftCircular", setter, self.cycles # RLC 1 cycle data = getter() s = (data << 1) + (data >> 7) self.flagsAndSetterFinish(s, setter, 0x80) - print self.cycles #self.cycles -= 1 def rotateLeftCircularA(self): Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboy.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboy.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboy.py Sun May 4 23:37:53 2008 @@ -95,10 +95,16 @@ ticks -= count def write(self, address, data): - self.getReceiver(address).write(address, data) + receiver = self.getReceiver(address) + if receiver==None: + raise Exception("invalid read address given") + receiver.write(address, data) def read(self, address): - self.getReceiver(address).read(address) + receiver = self.getReceiver(address) + if receiver==None: + raise Exception("invalid read address given") + return receiver.read(address) def getReceiver(self, address): if 0x0000 <= address <= 0x7FFF: Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/joypad.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/joypad.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/joypad.py Sun May 4 23:37:53 2008 @@ -23,18 +23,18 @@ def emulate(self, ticks): self.cycles -= ticks - if (self.cycles <= 0): - if (self.driver.isRaised()): + if self.cycles <= 0: + if self.driver.isRaised(): self.update() self.cycles = constants.JOYPAD_CLOCK def write(self, address, data): - if (address == constants.JOYP): + if address == constants.JOYP: self.joyp = (self.joyp & 0xC) + (data & 0x3) self.update() def read(self, address): - if (address == constants.JOYP): + if address == constants.JOYP: return (self.joyp << 4) + self.buttonCode return 0xFF Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_rom.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_rom.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_rom.py Sun May 4 23:37:53 2008 @@ -38,16 +38,21 @@ def test_rom4(): - py.test.skip("problem with resetBit") gameBoy = GameBoy() gameBoy.loadCartridgeFile(ROM_PATH+"/rom4/rom4.gb") gameBoy.emulate(EMULATION_CYCLES) + assert gameBoy.cpu.ime == False + assert gameBoy.cpu.halted == True + assert gameBoy.cpu.a.get() != 0xFF + def test_rom5(): gameBoy = GameBoy() gameBoy.loadCartridgeFile(ROM_PATH+"/rom5/rom5.gb") gameBoy.emulate(EMULATION_CYCLES) + # stop test + assert gameBoy.cpu.a.get() != 0xFF def test_rom6(): @@ -57,21 +62,18 @@ def test_rom7(): - py.test.skip("cpu bug in storeMemoryAtExpandedFetchAddressInA") gameBoy = GameBoy() gameBoy.loadCartridgeFile(ROM_PATH+"/rom7/rom7.gb") gameBoy.emulate(EMULATION_CYCLES) def test_rom8(): - py.test.skip("cpu bug in storeMemoryAtExpandedFetchAddressInA") gameBoy = GameBoy() gameBoy.loadCartridgeFile(ROM_PATH+"/rom8/rom8.gb") gameBoy.emulate(EMULATION_CYCLES) def test_rom9(): - py.test.skip("cpu bug in storeMemoryAtExpandedFetchAddressInA") gameBoy = GameBoy() gameBoy.loadCartridgeFile(ROM_PATH+"/rom9/rom9.gb") gameBoy.emulate(EMULATION_CYCLES) Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/video.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/video.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/video.py Sun May 4 23:37:53 2008 @@ -592,5 +592,5 @@ return self.pixels def updateDisplay(self): - self.resetPixels() + self.clearPixels() \ No newline at end of file From fijal at codespeak.net Mon May 5 10:41:44 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 5 May 2008 10:41:44 +0200 (CEST) Subject: [pypy-svn] r54430 - pypy/branch/io-improvements/pypy/rpython/test Message-ID: <20080505084144.E6DF716851F@codespeak.net> Author: fijal Date: Mon May 5 10:41:43 2008 New Revision: 54430 Modified: pypy/branch/io-improvements/pypy/rpython/test/test_runicode.py Log: these tests pass Modified: pypy/branch/io-improvements/pypy/rpython/test/test_runicode.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/test/test_runicode.py (original) +++ pypy/branch/io-improvements/pypy/rpython/test/test_runicode.py Mon May 5 10:41:43 2008 @@ -211,10 +211,6 @@ test_float = unsupported test_hlstr = unsupported - def test_find_empty_string(self): - py.test.skip("We should think how to solve this problem") - test_rfind_empty_string = test_find_empty_string - class TestLLtype(BaseTestRUnicode, LLRtypeMixin): EMPTY_STRING_HASH = -1 From fijal at codespeak.net Mon May 5 10:42:42 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 5 May 2008 10:42:42 +0200 (CEST) Subject: [pypy-svn] r54431 - pypy/branch/io-improvements/pypy/rpython/lltypesystem Message-ID: <20080505084242.C0A20168520@codespeak.net> Author: fijal Date: Mon May 5 10:42:42 2008 New Revision: 54431 Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/rstr.py Log: * Fix buggy memcopy * Leave clearer comment and explosion if tried with unicode Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/rstr.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/lltypesystem/rstr.py (original) +++ pypy/branch/io-improvements/pypy/rpython/lltypesystem/rstr.py Mon May 5 10:42:42 2008 @@ -16,7 +16,6 @@ staticAdtMethod, GcForwardReference from pypy.rpython.rmodel import Repr from pypy.rpython.lltypesystem import llmemory -from pypy.rlib.objectmodel import we_are_translated from pypy.tool.sourcetools import func_with_new_name # ____________________________________________________________ @@ -312,13 +311,13 @@ return result def ll_upper(s): - # XXX WUAAAA! this is not true anymore for unicode s_chars = s.chars s_len = len(s_chars) if s_len == 0: return s.empty() i = 0 - result = s.malloc(s_len) + result = mallocstr(s_len) + # ^^^^^^^^^ specifically to explode on unicode while i < s_len: ch = s_chars[i] if 'a' <= ch <= 'z': @@ -328,13 +327,13 @@ return result def ll_lower(s): - # XXX WUAAAA! this is not true anymore for unicode s_chars = s.chars s_len = len(s_chars) if s_len == 0: return s.empty() i = 0 - result = s.malloc(s_len) + result = mallocstr(s_len) + # ^^^^^^^^^ specifically to explode on unicode while i < s_len: ch = s_chars[i] if 'A' <= ch <= 'Z': @@ -606,7 +605,7 @@ while i < num_items: item_chars = items[i].chars item_len = len(item_chars) - copy_contents(result, items[i], res_index, 0, item_len) + copy_contents(items[i], result, 0, res_index, item_len) res_index += item_len i += 1 return result From fijal at codespeak.net Mon May 5 10:44:07 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 5 May 2008 10:44:07 +0200 (CEST) Subject: [pypy-svn] r54432 - in pypy/branch/io-improvements/pypy/rpython: . memory/gc memory/gctransform memory/test Message-ID: <20080505084407.2DB30168520@codespeak.net> Author: fijal Date: Mon May 5 10:44:06 2008 New Revision: 54432 Modified: pypy/branch/io-improvements/pypy/rpython/llinterp.py pypy/branch/io-improvements/pypy/rpython/memory/gc/base.py pypy/branch/io-improvements/pypy/rpython/memory/gctransform/boehm.py pypy/branch/io-improvements/pypy/rpython/memory/gctransform/framework.py pypy/branch/io-improvements/pypy/rpython/memory/gctransform/transform.py pypy/branch/io-improvements/pypy/rpython/memory/test/test_transformed_gc.py Log: * Enough support to make boehm realloc. * Implement boehm realloc via rffi, looks cleaner to me * Default, copying implementation that works on every gc. This whole speeds up certain use cases. Next step would be to have nicer interface for string builder Modified: pypy/branch/io-improvements/pypy/rpython/llinterp.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/llinterp.py (original) +++ pypy/branch/io-improvements/pypy/rpython/llinterp.py Mon May 5 10:44:06 2008 @@ -697,7 +697,7 @@ zero = flags.get('zero', False) return self.heap.malloc_nonmovable(obj, size, zero=zero) - def op_malloc_resizable_buffer(self, obj, size): + def op_malloc_resizable_buffer(self, obj, flags, size): return self.heap.malloc_resizable_buffer(obj, size) def op_resize_buffer(self, obj, new_size): Modified: pypy/branch/io-improvements/pypy/rpython/memory/gc/base.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/memory/gc/base.py (original) +++ pypy/branch/io-improvements/pypy/rpython/memory/gc/base.py Mon May 5 10:44:06 2008 @@ -7,6 +7,7 @@ needs_write_barrier = False malloc_zero_filled = False prebuilt_gc_objects_are_static_roots = True + can_realloc = False def set_query_functions(self, is_varsize, has_gcptr_in_varsize, is_gcarrayofgcptr, Modified: pypy/branch/io-improvements/pypy/rpython/memory/gctransform/boehm.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/memory/gctransform/boehm.py (original) +++ pypy/branch/io-improvements/pypy/rpython/memory/gctransform/boehm.py Mon May 5 10:44:06 2008 @@ -4,6 +4,8 @@ from pypy.rpython.lltypesystem import lltype, llmemory from pypy.objspace.flow.model import Constant from pypy.rpython.lltypesystem.lloperation import llop +from pypy.rpython.lltypesystem import rffi +from pypy.rpython import rmodel class BoehmGCTransformer(GCTransformer): malloc_zero_filled = True @@ -19,12 +21,19 @@ mh = mallocHelpers() mh.allocate = lambda size: llop.boehm_malloc(llmemory.Address, size) + c_realloc = rffi.llexternal('GC_REALLOC', [rffi.VOIDP, rffi.INT], + rffi.VOIDP) + def _realloc(ptr, size): + return llmemory.cast_ptr_to_adr(c_realloc(rffi.cast(rffi.VOIDP, ptr), size)) + mh.realloc = _realloc ll_malloc_fixedsize = mh._ll_malloc_fixedsize # XXX, do we need/want an atomic version of this function? ll_malloc_varsize_no_length = mh.ll_malloc_varsize_no_length ll_malloc_varsize = mh.ll_malloc_varsize + ll_realloc = mh.ll_realloc + if self.translator: self.malloc_fixedsize_ptr = self.inittime_helper( ll_malloc_fixedsize, [lltype.Signed], llmemory.Address) @@ -39,6 +48,9 @@ inline=False) self.weakref_deref_ptr = self.inittime_helper( ll_weakref_deref, [llmemory.WeakRefPtr], llmemory.Address) + self.realloc_ptr = self.inittime_helper( + ll_realloc, [llmemory.Address] + [lltype.Signed] * 4, + llmemory.Address) self.mixlevelannotator.finish() # for now self.mixlevelannotator.backend_optimize() @@ -48,6 +60,15 @@ def pop_alive_nopyobj(self, var, llops): pass + def _can_realloc(self): + return True + + def perform_realloc(self, hop, c_const_size, c_item_size, c_lengthofs): + op = hop.spaceop + args = [self.realloc_ptr, op.args[0], op.args[1], c_const_size, + c_item_size, c_lengthofs] + return hop.genop('direct_call', args, resulttype=llmemory.Address) + def gct_fv_gc_malloc(self, hop, flags, TYPE, c_size): # XXX same behavior for zero=True: in theory that's wrong if TYPE._is_atomic(): @@ -63,7 +84,6 @@ hop.genop("boehm_register_finalizer", [v_raw, c_finalizer_ptr]) return v_raw - def gct_fv_gc_malloc_varsize(self, hop, flags, TYPE, v_length, c_const_size, c_item_size, c_offset_to_length): # XXX same behavior for zero=True: in theory that's wrong Modified: pypy/branch/io-improvements/pypy/rpython/memory/gctransform/framework.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/memory/gctransform/framework.py (original) +++ pypy/branch/io-improvements/pypy/rpython/memory/gctransform/framework.py Mon May 5 10:44:06 2008 @@ -442,7 +442,7 @@ has_finalizer = bool(self.finalizer_funcptr_for_type(TYPE)) c_has_finalizer = rmodel.inputconst(lltype.Bool, has_finalizer) - if not op.opname.endswith('_varsize'): + if not op.opname.endswith('_varsize') and not flags.get('varsize'): #malloc_ptr = self.malloc_fixedsize_ptr zero = flags.get('zero', False) if (self.malloc_fast_ptr is not None and @@ -489,6 +489,9 @@ hop.genop("direct_call", [self.can_move_ptr, self.c_const_gc, v_addr], resultvar=op.result) + def _can_realloc(self): + return self.gcdata.gc.can_realloc + def gct_gc__disable_finalizers(self, hop): # cannot collect() op = hop.spaceop Modified: pypy/branch/io-improvements/pypy/rpython/memory/gctransform/transform.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/memory/gctransform/transform.py (original) +++ pypy/branch/io-improvements/pypy/rpython/memory/gctransform/transform.py Mon May 5 10:44:06 2008 @@ -455,6 +455,15 @@ return result mh.ll_malloc_varsize_no_length_zero = _ll_malloc_varsize_no_length_zero + def ll_realloc(ptr, length, constsize, itemsize, lengthoffset): + size = constsize + length * itemsize + result = mh.realloc(ptr, size) + if not result: + raise MemoryError() + (result + lengthoffset).signed[0] = length + return result + mh.ll_realloc = ll_realloc + return mh class GCTransformer(BaseGCTransformer): @@ -522,23 +531,52 @@ gct_malloc_nonmovable = gct_malloc gct_malloc_nonmovable_varsize = gct_malloc_varsize - - gct_malloc_resizable_buffer = gct_malloc_varsize + + def gct_malloc_resizable_buffer(self, hop): + flags = hop.spaceop.args[1].value + flags['varsize'] = True + flavor = flags['flavor'] + assert flavor != 'cpy', "cannot malloc CPython objects directly" + meth = getattr(self, 'gct_fv_%s_malloc_varsize' % flavor, None) + assert meth, "%s has no support for malloc_varsize with flavor %r" % (self, flavor) + return self.varsize_malloc_helper(hop, flags, meth, []) def gct_resize_buffer(self, hop): + if self._can_realloc(): + self._gct_resize_buffer_realloc(hop) + else: + self._gct_resize_buffer_no_realloc(hop) + + def _can_realloc(self): + return False + + def _gct_resize_buffer_realloc(self, hop): + def intconst(c): return rmodel.inputconst(lltype.Signed, c) + op = hop.spaceop + flags = {'flavor':'gc', 'varsize': True} + TYPE = op.args[0].concretetype.TO + ARRAY = TYPE._flds[TYPE._arrayfld] + offset_to_length = llmemory.FieldOffset(TYPE, TYPE._arrayfld) + \ + llmemory.ArrayLengthOffset(ARRAY) + c_const_size = intconst(llmemory.sizeof(TYPE, 0)) + c_item_size = intconst(llmemory.sizeof(ARRAY.OF)) + + c_lengthofs = intconst(offset_to_length) + v_raw = self.perform_realloc(hop, c_const_size, c_item_size, + c_lengthofs) + hop.cast_result(v_raw) + + def _gct_resize_buffer_no_realloc(self, hop): op = hop.spaceop meth = self.gct_fv_gc_malloc_varsize - flags = {'flavor':'gc'} + flags = {'flavor':'gc', 'varsize': True} self.varsize_malloc_helper(hop, flags, meth, []) # fish resvar v_newbuf = hop.llops[-1].result v_src = op.args[0] TYPE = v_src.concretetype.TO - v_arr = hop.genop('getfield', [v_src, rmodel.inputconst(lltype.Void, - TYPE._arrayfld)], - resulttype=getattr(TYPE, TYPE._arrayfld)) - v_lgt = hop.genop('getfield', [v_arr, rmodel.inputconst(lltype.Void, - 'length')], + c_fldname = rmodel.inputconst(lltype.Void, TYPE._arrayfld) + v_lgt = hop.genop('getinteriorarraysize', [v_src, c_fldname], resulttype=lltype.Signed) v_adrsrc = hop.genop('cast_ptr_to_adr', [v_src], resulttype=llmemory.Address) @@ -546,14 +584,21 @@ resulttype=llmemory.Address) ofs = (llmemory.offsetof(TYPE, TYPE._arrayfld) + llmemory.itemoffsetof(getattr(TYPE, TYPE._arrayfld), 0)) - v_ofs = rmodel.inputconst(lltype.Void, ofs) + v_ofs = rmodel.inputconst(lltype.Signed, ofs) v_adrsrc = hop.genop('adr_add', [v_adrsrc, v_ofs], resulttype=llmemory.Address) v_adrnewbuf = hop.genop('adr_add', [v_adrnewbuf, v_ofs], resulttype=llmemory.Address) - vlist = [v_adrsrc, v_adrnewbuf, v_lgt] + size = llmemory.sizeof(getattr(TYPE, TYPE._arrayfld).OF) + c_size = rmodel.inputconst(lltype.Signed, size) + v_lgtsym = hop.genop('int_mul', [c_size, v_lgt], + resulttype=lltype.Signed) + vlist = [v_adrsrc, v_adrnewbuf, v_lgtsym] hop.genop('raw_memcopy', vlist) - return v_newbuf + + def gct_finish_building_buffer(self, hop): + op = hop.spaceop + return hop.genop('same_as', op.args, resultvar=op.result) def varsize_malloc_helper(self, hop, flags, meth, extraargs): def intconst(c): return rmodel.inputconst(lltype.Signed, c) Modified: pypy/branch/io-improvements/pypy/rpython/memory/test/test_transformed_gc.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/memory/test/test_transformed_gc.py (original) +++ pypy/branch/io-improvements/pypy/rpython/memory/test/test_transformed_gc.py Mon May 5 10:44:06 2008 @@ -493,7 +493,6 @@ assert run([]) == int(self.GC_CAN_MOVE) def test_resizable_buffer(self): - py.test.skip("Does not work") from pypy.rpython.lltypesystem.rstr import STR from pypy.rpython.annlowlevel import hlstr from pypy.rlib import rgc From fijal at codespeak.net Mon May 5 10:45:05 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 5 May 2008 10:45:05 +0200 (CEST) Subject: [pypy-svn] r54433 - pypy/branch/io-improvements/pypy/translator/c/test Message-ID: <20080505084505.78390168521@codespeak.net> Author: fijal Date: Mon May 5 10:45:03 2008 New Revision: 54433 Modified: pypy/branch/io-improvements/pypy/translator/c/test/test_boehm.py Log: A (passing) test for boehm and resizable_buffer Modified: pypy/branch/io-improvements/pypy/translator/c/test/test_boehm.py ============================================================================== --- pypy/branch/io-improvements/pypy/translator/c/test/test_boehm.py (original) +++ pypy/branch/io-improvements/pypy/translator/c/test/test_boehm.py Mon May 5 10:45:03 2008 @@ -377,6 +377,21 @@ c_fn = self.getcompiled(fn, []) assert c_fn() == False + def test_resizable_buffer(self): + from pypy.rpython.lltypesystem.rstr import STR + from pypy.rpython.annlowlevel import hlstr + from pypy.rlib import rgc + + def f(): + ptr = rgc.resizable_buffer_of_shape(STR, 1) + ptr.chars[0] = 'a' + ptr = rgc.resize_buffer(ptr, 2) + ptr.chars[1] = 'b' + return hlstr(rgc.finish_building_buffer(ptr)) == "ab" + + run = self.getcompiled(f) + assert run() == True + # reusing some tests from pypy.rpython.memory.test.snippet large_tests_ok = True From fijal at codespeak.net Mon May 5 10:58:13 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 5 May 2008 10:58:13 +0200 (CEST) Subject: [pypy-svn] r54434 - pypy/dist/pypy/doc Message-ID: <20080505085813.98B37168520@codespeak.net> Author: fijal Date: Mon May 5 10:58:13 2008 New Revision: 54434 Modified: pypy/dist/pypy/doc/rffi.txt Log: clarify Modified: pypy/dist/pypy/doc/rffi.txt ============================================================================== --- pypy/dist/pypy/doc/rffi.txt (original) +++ pypy/dist/pypy/doc/rffi.txt Mon May 5 10:58:13 2008 @@ -6,7 +6,7 @@ ------- This document describes an FFI for RPython language, concentrating -only (right now) on low-level backends like C or LLVM. It describes +on low-level backends like C or LLVM. It describes how to declare and call low-level (C) functions from RPython level. Declaring low-level external function @@ -69,6 +69,7 @@ .. _`extfunc.py`: http://codespeak.net/svn/pypy/dist/pypy/rpython/extfunc.py + OO backends ----------- From cami at codespeak.net Mon May 5 15:40:45 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Mon, 5 May 2008 15:40:45 +0200 (CEST) Subject: [pypy-svn] r54440 - in pypy/branch/gameboy-emulator/pypy/lang/gameboy: . test Message-ID: <20080505134045.749981684C1@codespeak.net> Author: cami Date: Mon May 5 15:40:43 2008 New Revision: 54440 Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_register.py Log: changed register constructor Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py Mon May 5 15:40:43 2008 @@ -28,7 +28,8 @@ # ------------------------------------------------------------------------------ class DoubleRegister(Register): - def __init__(self, cpu, hi=None, lo=None, resetValue=None): + + def __init__(self, cpu, hi=None, lo=None, resetValue=0): self.cpu = cpu if isinstance(hi, (Register)) : self.hi = hi @@ -38,10 +39,7 @@ self.lo = Register(self.cpu) else: self.lo = lo - if (resetValue != None): - self.resetValue = resetValue - elif (hi!=None and lo==None and resetValue==None): - self.resetValue = hi + self.resetValue = resetValue def set(self, hi=0, lo=None, useCycles=True): if (lo is None): @@ -205,8 +203,8 @@ self.hl = DoubleRegister(self, self.h, self.l, constants.RESET_HL) self.hli = ImmediatePseudoRegister(self, self.hl) - self.pc = DoubleRegister(self, constants.RESET_PC) - self.sp = DoubleRegister(self, constants.RESET_SP) + self.pc = DoubleRegister(self, resetValue=constants.RESET_PC) + self.sp = DoubleRegister(self, resetValue=constants.RESET_SP) self.a = Register(self, constants.RESET_A) self.f = FlagRegister(self) Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_register.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_register.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_register.py Mon May 5 15:40:43 2008 @@ -152,8 +152,9 @@ def test_double_register_reset(): value = 0x1234; - register = DoubleRegister(get_cpu(), value) + register = DoubleRegister(get_cpu(), resetValue=value) register.set(value+1) assert register.get() == value+1; register.reset() - assert register.get() == value \ No newline at end of file + assert register.get() == value + \ No newline at end of file From tverwaes at codespeak.net Mon May 5 15:56:53 2008 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Mon, 5 May 2008 15:56:53 +0200 (CEST) Subject: [pypy-svn] r54441 - pypy/branch/gameboy-emulator/pypy/translator/goal Message-ID: <20080505135653.17BBD168423@codespeak.net> Author: tverwaes Date: Mon May 5 15:56:53 2008 New Revision: 54441 Added: pypy/branch/gameboy-emulator/pypy/translator/goal/targetgbrom4.py Log: added rom4 target Added: pypy/branch/gameboy-emulator/pypy/translator/goal/targetgbrom4.py ============================================================================== --- (empty file) +++ pypy/branch/gameboy-emulator/pypy/translator/goal/targetgbrom4.py Mon May 5 15:56:53 2008 @@ -0,0 +1,34 @@ +import os +import py +from pypy.lang.gameboy import constants +from pypy.lang.gameboy.cpu import * +from pypy.lang.gameboy.cartridge import * +from pypy.lang.gameboy.gameboy import * + + +ROM_PATH = str(py.magic.autopath().dirpath().dirpath().dirpath())+"lang/gameboy/rom" +EMULATION_CYCLES = 64 + + +# This loads the whole mini.image in advance. At run-time, +# it executes the tinyBenchmark. In this way we get an RPython +# "image" frozen into the executable, mmap'ed by the OS from +# there and loaded lazily when needed :-) + + +# XXX this only compiles if sys.recursionlimit is high enough! +# On non-Linux platforms I don't know if there is enough stack to +# compile... +#sys.setrecursionlimit(100000) + + +def entry_point(argv): + gameBoy = GameBoy() + gameBoy.loadCartridgeFile(ROM_PATH+"/rom4/rom4.gb") + gameBoy.emulate(EMULATION_CYCLES) + + +# _____ Define and setup target ___ + +def target(*args): + return entry_point, None From arigo at codespeak.net Mon May 5 17:37:24 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 5 May 2008 17:37:24 +0200 (CEST) Subject: [pypy-svn] r54442 - pypy/dist/pypy/rpython Message-ID: <20080505153724.149311684CB@codespeak.net> Author: arigo Date: Mon May 5 17:37:22 2008 New Revision: 54442 Modified: pypy/dist/pypy/rpython/extfunc.py Log: Typo Modified: pypy/dist/pypy/rpython/extfunc.py ============================================================================== --- pypy/dist/pypy/rpython/extfunc.py (original) +++ pypy/dist/pypy/rpython/extfunc.py Mon May 5 17:37:22 2008 @@ -257,7 +257,7 @@ if llimpl: lltypeimpl = staticmethod(llimpl) if ooimpl: - ootypeimpl = staticmethd(ooimpl) + ootypeimpl = staticmethod(ooimpl) if llfakeimpl: lltypefakeimpl = staticmethod(llfakeimpl) if oofakeimpl: From arigo at codespeak.net Mon May 5 17:41:13 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 5 May 2008 17:41:13 +0200 (CEST) Subject: [pypy-svn] r54443 - in pypy/dist/pypy: module/posix module/posix/test rlib Message-ID: <20080505154113.438D21684CD@codespeak.net> Author: arigo Date: Mon May 5 17:41:10 2008 New Revision: 54443 Modified: pypy/dist/pypy/module/posix/__init__.py pypy/dist/pypy/module/posix/app_posix.py pypy/dist/pypy/module/posix/interp_posix.py pypy/dist/pypy/module/posix/test/test_posix2.py pypy/dist/pypy/rlib/rposix.py Log: Move this loop at interp-level, using an os.closerange()-alike helper (it's a new built-in in Python 2.6). Modified: pypy/dist/pypy/module/posix/__init__.py ============================================================================== --- pypy/dist/pypy/module/posix/__init__.py (original) +++ pypy/dist/pypy/module/posix/__init__.py Mon May 5 17:41:10 2008 @@ -27,6 +27,7 @@ 'isatty' : 'interp_posix.isatty', 'read' : 'interp_posix.read', 'close' : 'interp_posix.close', + 'closerange': 'interp_posix.closerange', 'fstat' : 'interp_posix.fstat', 'stat' : 'interp_posix.stat', 'lstat' : 'interp_posix.lstat', Modified: pypy/dist/pypy/module/posix/app_posix.py ============================================================================== --- pypy/dist/pypy/module/posix/app_posix.py (original) +++ pypy/dist/pypy/module/posix/app_posix.py Mon May 5 17:41:10 2008 @@ -115,8 +115,7 @@ else: os.dup2(read_end, 0) os.close(write_end) - for i in range(3, MAXFD): # XXX this loop can be slow - try_close(i) + os.closerange(3, MAXFD) cmd = ['/bin/sh', '-c', command] os.execvp(cmd[0], cmd) finally: Modified: pypy/dist/pypy/module/posix/interp_posix.py ============================================================================== --- pypy/dist/pypy/module/posix/interp_posix.py (original) +++ pypy/dist/pypy/module/posix/interp_posix.py Mon May 5 17:41:10 2008 @@ -1,4 +1,5 @@ from pypy.interpreter.baseobjspace import ObjSpace, W_Root +from pypy.rlib import rposix from pypy.rlib.rarithmetic import r_longlong from pypy.rlib.unroll import unrolling_iterable from pypy.interpreter.error import OperationError, wrap_oserror @@ -70,6 +71,11 @@ raise wrap_oserror(space, e) close.unwrap_spec = [ObjSpace, int] +def closerange(fd_low, fd_high): + """Closes all file descriptors in [fd_low, fd_high), ignoring errors.""" + rposix.closerange(fd_low, fd_high) +closerange.unwrap_spec = [int, int] + def ftruncate(space, fd, length): """Truncate a file to a specified length.""" try: Modified: pypy/dist/pypy/module/posix/test/test_posix2.py ============================================================================== --- pypy/dist/pypy/module/posix/test/test_posix2.py (original) +++ pypy/dist/pypy/module/posix/test/test_posix2.py Mon May 5 17:41:10 2008 @@ -377,6 +377,23 @@ assert os.WTERMSIG(status1) == self.SIGABRT pass # <- please, inspect.getsource(), don't crash + def test_closerange(self): + os = self.posix + if not hasattr(os, 'closerange'): + skip("missing os.closerange()") + fds = [os.open(self.path + str(i), os.O_CREAT|os.O_WRONLY, 0777) + for i in range(15)] + fds.sort() + start = fds.pop() + stop = start + 1 + while len(fds) > 3 and fds[-1] == start - 1: + start = fds.pop() + os.closerange(start, stop) + for fd in fds: + os.close(fd) # should not have been closed + for fd in range(start, stop): + raises(OSError, os.fstat, fd) # should have been closed + class AppTestEnvironment(object): def setup_class(cls): Modified: pypy/dist/pypy/rlib/rposix.py ============================================================================== --- pypy/dist/pypy/rlib/rposix.py (original) +++ pypy/dist/pypy/rlib/rposix.py Mon May 5 17:41:10 2008 @@ -1,3 +1,4 @@ +import os from pypy.rpython.lltypesystem.rffi import CConstant, CExternVariable, INT from pypy.rpython.lltypesystem import lltype, ll2ctypes from pypy.translator.tool.cbuild import ExternalCompilationInfo @@ -26,3 +27,11 @@ def get_errno(): return intmask(_get_errno()) + +def closerange(fd_low, fd_high): + # this behaves like os.closerange() from Python 2.6. + for fd in xrange(fd_low, fd_high): + try: + os.close(fd) + except OSError: + pass From arigo at codespeak.net Mon May 5 21:56:10 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 5 May 2008 21:56:10 +0200 (CEST) Subject: [pypy-svn] r54450 - in pypy/branch/gc-tweak/pypy/rpython: lltypesystem memory memory/gc memory/gctransform Message-ID: <20080505195610.DDC56168432@codespeak.net> Author: arigo Date: Mon May 5 21:56:10 2008 New Revision: 54450 Modified: pypy/branch/gc-tweak/pypy/rpython/lltypesystem/opimpl.py pypy/branch/gc-tweak/pypy/rpython/memory/gc/generation.py pypy/branch/gc-tweak/pypy/rpython/memory/gc/hybrid.py pypy/branch/gc-tweak/pypy/rpython/memory/gc/semispace.py pypy/branch/gc-tweak/pypy/rpython/memory/gctransform/framework.py pypy/branch/gc-tweak/pypy/rpython/memory/gctypelayout.py pypy/branch/gc-tweak/pypy/rpython/memory/gcwrapper.py Log: Experimental. Build on top of the GenerationGC's GCFLAG_NO_HEAP_PTRS flag to make the HybridGC a full 3-generations collector. Unsure if the additional complexity is worth the trouble. Modified: pypy/branch/gc-tweak/pypy/rpython/lltypesystem/opimpl.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/lltypesystem/opimpl.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/lltypesystem/opimpl.py Mon May 5 21:56:10 2008 @@ -384,7 +384,8 @@ def op_debug_print(*args): for arg in args: - print arg + print arg, + print # ____________________________________________________________ Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gc/generation.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/memory/gc/generation.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/memory/gc/generation.py Mon May 5 21:56:10 2008 @@ -16,8 +16,12 @@ # pointer to a young object. GCFLAG_NO_YOUNG_PTRS = SemiSpaceGC.first_unused_gcflag << 0 -# The following flag is set for static roots which are not on the list -# of static roots yet, but will appear with write barrier +# The following flag is set on some last-generation objects (== prebuilt +# objects for GenerationGC, but see also HybridGC). The flag is set +# unless the object is already listed in 'last_generation_root_objects'. +# When a pointer is written inside an object with GCFLAG_NO_HEAP_PTRS +# set, the write_barrier clears the flag and adds the object to +# 'last_generation_root_objects'. GCFLAG_NO_HEAP_PTRS = SemiSpaceGC.first_unused_gcflag << 1 class GenerationGC(SemiSpaceGC): @@ -70,6 +74,7 @@ self.lb_young_var_basesize = sz def setup(self): + self.last_generation_root_objects = self.AddressStack() SemiSpaceGC.setup(self) self.set_nursery_size(self.initial_nursery_size) # the GC is fully setup now. The rest can make use of it. @@ -281,6 +286,31 @@ obj = self.young_objects_with_weakrefs.pop() self.objects_with_weakrefs.append(obj) + def collect_roots(self): + self.root_walker.walk_roots( + SemiSpaceGC._collect_root, # stack roots + SemiSpaceGC._collect_root, # static in prebuilt non-gc structures + None) # we don't need the static in prebuilt gc objects + self.collect_last_generation_roots() + + def collect_last_generation_roots(self): + stack = self.last_generation_root_objects + self.last_generation_root_objects = self.AddressStack() + while stack.non_empty(): + obj = stack.pop() + self.header(obj).tid |= GCFLAG_NO_HEAP_PTRS + # ^^^ the flag we just added will be removed immediately if + # the object still contains pointers to younger objects + self.trace(obj, self._trace_external_obj, obj) + stack.delete() + + def _trace_external_obj(self, pointer, obj): + addr = pointer.address[0] + if addr != NULL: + newaddr = self.copy(addr) + pointer.address[0] = newaddr + self.write_into_last_generation_obj(obj, newaddr) + # ____________________________________________________________ # Implementation of nursery-only collections @@ -390,25 +420,28 @@ if self.header(addr_struct).tid & GCFLAG_NO_YOUNG_PTRS: self.remember_young_pointer(addr_struct, newvalue) - def append_to_static_roots(self, pointer, arg): - self.root_walker.append_static_root(pointer) - - def move_to_static_roots(self, addr_struct): - objhdr = self.header(addr_struct) - objhdr.tid &= ~GCFLAG_NO_HEAP_PTRS - self.trace(addr_struct, self.append_to_static_roots, None) - def remember_young_pointer(self, addr_struct, addr): ll_assert(not self.is_in_nursery(addr_struct), "nursery object with GCFLAG_NO_YOUNG_PTRS") - oldhdr = self.header(addr_struct) if self.is_in_nursery(addr): self.old_objects_pointing_to_young.append(addr_struct) - oldhdr.tid &= ~GCFLAG_NO_YOUNG_PTRS - if oldhdr.tid & GCFLAG_NO_HEAP_PTRS: - self.move_to_static_roots(addr_struct) + self.header(addr_struct).tid &= ~GCFLAG_NO_YOUNG_PTRS + elif addr == NULL: + return + self.write_into_last_generation_obj(addr_struct, addr) remember_young_pointer._dont_inline_ = True + def write_into_last_generation_obj(self, addr_struct, addr): + objhdr = self.header(addr_struct) + if objhdr.tid & GCFLAG_NO_HEAP_PTRS: + if not self.is_last_generation(addr): + objhdr.tid &= ~GCFLAG_NO_HEAP_PTRS + self.last_generation_root_objects.append(addr_struct) + + def is_last_generation(self, obj): + # overridden by HybridGC + return (self.header(obj).tid & GCFLAG_EXTERNAL) != 0 + # ____________________________________________________________ import os Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gc/hybrid.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/memory/gc/hybrid.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/memory/gc/hybrid.py Mon May 5 21:56:10 2008 @@ -2,30 +2,72 @@ from pypy.rpython.memory.gc.semispace import SemiSpaceGC from pypy.rpython.memory.gc.semispace import DEBUG_PRINT from pypy.rpython.memory.gc.generation import GenerationGC, GCFLAG_FORWARDED +from pypy.rpython.memory.gc.semispace import GCFLAG_EXTERNAL from pypy.rpython.memory.gc.generation import GCFLAG_NO_YOUNG_PTRS +from pypy.rpython.memory.gc.generation import GCFLAG_NO_HEAP_PTRS from pypy.rpython.lltypesystem import lltype, llmemory, llarena from pypy.rpython.lltypesystem.llmemory import raw_malloc_usage from pypy.rpython.lltypesystem.lloperation import llop from pypy.rlib.debug import ll_assert from pypy.rlib.rarithmetic import ovfcheck -# The "age" of an object is the number of times it is copied between the -# two semispaces. When an object would reach MAX_SEMISPACE_AGE, it is -# instead copied to a nonmoving location. For example, a value of 4 +# _______in the semispaces_________ ______external (non-moving)_____ +# / \ / \ +# ___raw_malloc'ed__ _prebuilt_ +# +----------------------------------+ / \ / \ +# | | | | | | | | +# | | | | | | | | age < max age == max +# |nur-|o|o|o|o| | | +---+ +---+ +---+ +# |sery|b|b|b|b|free| empty | |obj| |obj| |obj| +# | |j|j|j|j| | | +---+ +---+ +---+ +# | | | | | | | | +---+ +---+ +---+ +# +-----------------+----------------+ |obj| |obj| |obj| +# age <= max +---+ +---+ +---+ +# +# |gen1|------------- generation 2 -----------------|-----generation 3-----| +# +# Object lists: +# * gen2_rawmalloced_objects +# * gen3_rawmalloced_objects +# * old_objects_pointing_to_young: gen2or3 objs that point to gen1 objs +# * last_generation_root_objects: gen3 objs that point to gen1or2 objs +# +# How to tell the objects apart: +# * external: tid & GCFLAG_EXTERNAL +# * gen1: is_in_nursery(obj) +# * gen3: (tid & (GCFLAG_EXTERNAL|GCFLAG_AGE_MASK)) == +# (GCFLAG_EXTERNAL|GCFLAG_AGE_MAX) +# +# Some invariants: +# * gen3 are either GCFLAG_NO_HEAP_PTRS or in 'last_generation_root_objects' +# * between collections, GCFLAG_UNVISITED set exactly for gen2_rawmalloced +# +# A malloc_varsize() of large objects returns objects that are external +# but initially of generation 2. Old objects from the semispaces are +# moved to external objects directly as generation 3. + +# The "age" of an object is the number of times it survived a full +# collections, without counting the step that moved it out of the nursery. +# When a semispace-based object would grow older than MAX_SEMISPACE_AGE, +# it is instead copied to a nonmoving location. For example, a value of 3 # ensures that an object is copied at most 5 times in total: from the # nursery to the semispace, then three times between the two spaces, # then one last time to a nonmoving location. -MAX_SEMISPACE_AGE = 4 +MAX_SEMISPACE_AGE = 3 GCFLAG_UNVISITED = GenerationGC.first_unused_gcflag << 0 _gcflag_next_bit = GenerationGC.first_unused_gcflag << 1 GCFLAG_AGE_ONE = _gcflag_next_bit -GCFLAG_AGE_MAX = _gcflag_next_bit * (MAX_SEMISPACE_AGE-1) +GCFLAG_AGE_MAX = _gcflag_next_bit * MAX_SEMISPACE_AGE GCFLAG_AGE_MASK = 0 while GCFLAG_AGE_MASK < GCFLAG_AGE_MAX: GCFLAG_AGE_MASK |= _gcflag_next_bit _gcflag_next_bit <<= 1 +# The 3rd generation objects are only collected after the following +# number of calls to semispace_collect(): +GENERATION3_COLLECT_THRESHOLD = 20 + class HybridGC(GenerationGC): """A two-generations semi-space GC like the GenerationGC, @@ -33,6 +75,7 @@ they are allocated via raw_malloc/raw_free in a mark-n-sweep fashion. """ first_unused_gcflag = _gcflag_next_bit + prebuilt_gc_objects_are_static_roots = True # the following values override the default arguments of __init__ when # translating to a real backend. @@ -66,10 +109,12 @@ self.large_objects_collect_trigger = self.space_size if DEBUG_PRINT: self._initial_trigger = self.large_objects_collect_trigger - self.pending_external_object_list = self.AddressDeque() + self.rawmalloced_objects_to_trace = self.AddressStack() + self.count_semispaceonly_collects = 0 def setup(self): - self.large_objects_list = self.AddressDeque() + self.gen2_rawmalloced_objects = self.AddressStack() + self.gen3_rawmalloced_objects = self.AddressStack() GenerationGC.setup(self) def set_max_heap_size(self, size): @@ -184,7 +229,7 @@ # need to follow suit. llmemory.raw_memclear(result, totalsize) size_gc_header = self.gcheaderbuilder.size_gc_header - self.large_objects_list.append(result + size_gc_header) + self.gen2_rawmalloced_objects.append(result + size_gc_header) return result def allocate_external_object(self, totalsize): @@ -192,19 +237,62 @@ # If so, we'd also use arena_reset() in malloc_varsize_marknsweep(). return llmemory.raw_malloc(totalsize) + def init_gc_object_immortal(self, addr, typeid, + flags=(GCFLAG_NO_YOUNG_PTRS | + GCFLAG_NO_HEAP_PTRS | + GCFLAG_AGE_MAX)): + GenerationGC.init_gc_object_immortal(self, addr, typeid, flags) + + # ___________________________________________________________________ + # collect() and semispace_collect() are not synonyms in this GC: the + # former is a complete collect, while the latter is only collecting + # the semispaces and not always doing the mark-n-sweep pass over the + # external objects of 3rd generation. + + def collect(self): + self.count_semispaceonly_collects = GENERATION3_COLLECT_THRESHOLD + GenerationGC.collect(self) + + def is_collecting_gen3(self): + count = self.count_semispaceonly_collects + return count >= GENERATION3_COLLECT_THRESHOLD + # ___________________________________________________________________ # the following methods are hook into SemiSpaceGC.semispace_collect() def starting_full_collect(self): - # At the start of a collection, all raw_malloc'ed objects should - # have the GCFLAG_UNVISITED bit set. No other object ever has - # this bit set. - ll_assert(not self.pending_external_object_list.non_empty(), - "pending_external_object_list should be empty at start") + # At the start of a collection, the GCFLAG_UNVISITED bit is set + # exactly on the objects in gen2_rawmalloced_objects. Only + # raw_malloc'ed objects can ever have this bit set. + self.count_semispaceonly_collects += 1 + if self.is_collecting_gen3(): + # set the GCFLAG_UNVISITED on all rawmalloced generation-3 objects + # as well, to let them be recorded by visit_external_object() + self.gen3_rawmalloced_objects.foreach(self._set_gcflag_unvisited, + None) + ll_assert(not self.rawmalloced_objects_to_trace.non_empty(), + "rawmalloced_objects_to_trace should be empty at start") if DEBUG_PRINT: self._nonmoving_copy_count = 0 self._nonmoving_copy_size = 0 + def _set_gcflag_unvisited(self, obj, ignored): + ll_assert(not (self.header(obj).tid & GCFLAG_UNVISITED), + "bogus GCFLAG_UNVISITED on gen3 obj") + self.header(obj).tid |= GCFLAG_UNVISITED + + def collect_roots(self): + if not self.is_collecting_gen3(): + GenerationGC.collect_roots(self) + else: + # as we don't record which prebuilt gc objects point to + # rawmalloced generation 3 objects, we have to trace all + # the prebuilt gc objects. + self.root_walker.walk_roots( + SemiSpaceGC._collect_root, # stack roots + SemiSpaceGC._collect_root, # static in prebuilt non-gc structs + SemiSpaceGC._collect_root) # static in prebuilt gc objects + def surviving(self, obj): # To use during a collection. The objects that survive are the # ones with GCFLAG_FORWARDED set and GCFLAG_UNVISITED not set. @@ -213,12 +301,16 @@ flags = self.header(obj).tid & (GCFLAG_FORWARDED|GCFLAG_UNVISITED) return flags == GCFLAG_FORWARDED + def is_last_generation(self, obj): + return ((self.header(obj).tid & (GCFLAG_EXTERNAL|GCFLAG_AGE_MASK)) == + (GCFLAG_EXTERNAL|GCFLAG_AGE_MAX)) + def visit_external_object(self, obj): hdr = self.header(obj) if hdr.tid & GCFLAG_UNVISITED: # This is a not-visited-yet raw_malloced object. hdr.tid -= GCFLAG_UNVISITED - self.pending_external_object_list.append(obj) + self.rawmalloced_objects_to_trace.append(obj) def make_a_copy(self, obj, objsize): # During a full collect, all copied objects might implicitly come @@ -258,8 +350,14 @@ hdr = self.header(newobj) hdr.tid |= self.GCFLAGS_FOR_NEW_EXTERNAL_OBJECTS # GCFLAG_UNVISITED is not set - self.large_objects_list.append(newobj) - self.pending_external_object_list.append(newobj) + # GCFLAG_NO_HEAP_PTRS is not set either, conservatively. It may be + # set by the next collection's collect_last_generation_roots(). + # This old object is immediately put at generation 3. + ll_assert(self.is_last_generation(newobj), + "make_a_nonmoving_copy: object too young") + self.gen3_rawmalloced_objects.append(newobj) + self.last_generation_root_objects.append(newobj) + self.rawmalloced_objects_to_trace.append(newobj) # visit me return newobj def scan_copied(self, scan): @@ -270,23 +368,62 @@ newscan = GenerationGC.scan_copied(self, scan) progress = newscan != scan scan = newscan - while self.pending_external_object_list.non_empty(): - obj = self.pending_external_object_list.popleft() + while self.rawmalloced_objects_to_trace.non_empty(): + obj = self.rawmalloced_objects_to_trace.pop() self.trace_and_copy(obj) progress = True return scan def finished_full_collect(self): - ll_assert(not self.pending_external_object_list.non_empty(), - "pending_external_object_list should be empty at end") - # free all mark-n-sweep-managed objects that have not been marked - large_objects = self.large_objects_list - remaining_large_objects = self.AddressDeque() + ll_assert(not self.rawmalloced_objects_to_trace.non_empty(), + "rawmalloced_objects_to_trace should be empty at end") + if DEBUG_PRINT: + llop.debug_print(lltype.Void, + "| [hybrid] made nonmoving: ", + self._nonmoving_copy_size, "bytes in", + self._nonmoving_copy_count, "objs") + # sweep the nonmarked rawmalloced objects + if self.is_collecting_gen3(): + self.sweep_rawmalloced_objects(generation=3) + self.sweep_rawmalloced_objects(generation=2) + # As we just collected, it's fine to raw_malloc'ate up to space_size + # bytes again before we should force another collect. + self.large_objects_collect_trigger = self.space_size + if self.is_collecting_gen3(): + self.count_semispaceonly_collects = 0 + if DEBUG_PRINT: + self._initial_trigger = self.large_objects_collect_trigger + + def sweep_rawmalloced_objects(self, generation): + # free all the rawmalloced objects of the specified generation + # that have not been marked + if generation == 2: + objects = self.gen2_rawmalloced_objects + # generation 2 sweep: if A points to an object object B that + # moves from gen2 to gen3, it's possible that A no longer points + # to any gen2 object. In this case, A remains a bit too long in + # last_generation_root_objects, but this will be fixed by the + # next collect_last_generation_roots(). + else: + objects = self.gen3_rawmalloced_objects + # generation 3 sweep: remove from last_generation_root_objects + # all the objects that we are about to free + gen3roots = self.last_generation_root_objects + newgen3roots = self.AddressStack() + while gen3roots.non_empty(): + obj = gen3roots.pop() + if not (self.header(obj).tid & GCFLAG_UNVISITED): + newgen3roots.append(obj) + gen3roots.delete() + self.last_generation_root_objects = newgen3roots + + surviving_objects = self.AddressStack() if DEBUG_PRINT: alive_count = alive_size = 0 if DEBUG_PRINT: dead_count = dead_size = 0 - while large_objects.non_empty(): - obj = large_objects.popleft() - if self.header(obj).tid & GCFLAG_UNVISITED: + while objects.non_empty(): + obj = objects.pop() + tid = self.header(obj).tid + if tid & GCFLAG_UNVISITED: if DEBUG_PRINT:dead_count+=1 if DEBUG_PRINT:dead_size+=raw_malloc_usage(self.get_size(obj)) addr = obj - self.gcheaderbuilder.size_gc_header @@ -294,25 +431,35 @@ else: if DEBUG_PRINT:alive_count+=1 if DEBUG_PRINT:alive_size+=raw_malloc_usage(self.get_size(obj)) - self.header(obj).tid |= GCFLAG_UNVISITED - remaining_large_objects.append(obj) - large_objects.delete() - self.large_objects_list = remaining_large_objects - # As we just collected, it's fine to raw_malloc'ate up to space_size - # bytes again before we should force another collect. - self.large_objects_collect_trigger = self.space_size - + if generation == 3: + surviving_objects.append(obj) + else: + ll_assert((tid & GCFLAG_AGE_MASK) < GCFLAG_AGE_MAX, + "wrong age for generation 2 object") + tid += GCFLAG_AGE_ONE + if (tid & GCFLAG_AGE_MASK) == GCFLAG_AGE_MAX: + # the object becomes part of generation 3 + self.gen3_rawmalloced_objects.append(obj) + # GCFLAG_NO_HEAP_PTRS not set yet, conservatively + self.last_generation_root_objects.append(obj) + else: + # the object stays in generation 2 + tid |= GCFLAG_UNVISITED + surviving_objects.append(obj) + self.header(obj).tid = tid + objects.delete() + if generation == 2: + self.gen2_rawmalloced_objects = surviving_objects + else: + self.gen3_rawmalloced_objects = surviving_objects if DEBUG_PRINT: - self._initial_trigger = self.large_objects_collect_trigger - llop.debug_print(lltype.Void, - "| [hybrid] made nonmoving: ", - self._nonmoving_copy_size, "bytes in", - self._nonmoving_copy_count, "objs") llop.debug_print(lltype.Void, - "| [hybrid] nonmoving now alive: ", + "| [hyb] gen", generation, + "nonmoving now alive: ", alive_size, "bytes in", alive_count, "objs") llop.debug_print(lltype.Void, - "| [hybrid] nonmoving freed: ", + "| [hyb] gen", generation, + "nonmoving freed: ", dead_size, "bytes in", dead_count, "objs") Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gc/semispace.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/memory/gc/semispace.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/memory/gc/semispace.py Mon May 5 21:56:10 2008 @@ -21,7 +21,7 @@ GCFLAG_EXTERNAL = first_gcflag << 1 GCFLAG_FINALIZATION_ORDERING = first_gcflag << 2 -DEBUG_PRINT = False +DEBUG_PRINT = True memoryError = MemoryError() class SemiSpaceGC(MovingGCBase): @@ -205,6 +205,7 @@ self.semispace_collect() # the indirection is required by the fact that collect() is referred # to by the gc transformer, and the default argument would crash + # (this is also a hook for the HybridGC) def semispace_collect(self, size_changing=False): if DEBUG_PRINT: Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gctransform/framework.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/memory/gctransform/framework.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/memory/gctransform/framework.py Mon May 5 21:56:10 2008 @@ -391,11 +391,8 @@ self.layoutbuilder.addresses_of_static_ptrs_in_nongc + self.layoutbuilder.addresses_of_static_ptrs) log.info("found %s static roots" % (len(addresses_of_static_ptrs), )) - additional_ptrs = self.layoutbuilder.additional_roots_sources - log.info("additional %d potential static roots" % additional_ptrs) ll_static_roots_inside = lltype.malloc(lltype.Array(llmemory.Address), - len(addresses_of_static_ptrs) + - additional_ptrs, + len(addresses_of_static_ptrs), immortal=True) for i in range(len(addresses_of_static_ptrs)): ll_static_roots_inside[i] = addresses_of_static_ptrs[i] @@ -788,10 +785,6 @@ def setup_root_walker(self): pass - def append_static_root(self, adr): - self.gcdata.static_root_end.address[0] = adr - self.gcdata.static_root_end += sizeofaddr - def walk_roots(self, collect_stack_root, collect_static_in_prebuilt_nongc, collect_static_in_prebuilt_gc): Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gctypelayout.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/memory/gctypelayout.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/memory/gctypelayout.py Mon May 5 21:56:10 2008 @@ -193,10 +193,6 @@ self.addresses_of_static_ptrs = [] # this lists contains pointers in raw Structs and Arrays self.addresses_of_static_ptrs_in_nongc = [] - # if not gc.prebuilt_gc_objects_are_static_roots, then - # additional_roots_sources counts the number of locations - # within prebuilt GC objects that are of type Ptr(Gc) - self.additional_roots_sources = 0 self.finalizer_funcptrs = {} self.offsettable_cache = {} self.next_typeid_cache = {} @@ -292,8 +288,6 @@ adr = llmemory.cast_ptr_to_adr(value._as_ptr()) if TYPE._gckind == "gc": if not gc.prebuilt_gc_objects_are_static_roots: - for a in gc_pointers_inside(value, adr): - self.additional_roots_sources += 1 return else: appendto = self.addresses_of_static_ptrs Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gcwrapper.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/memory/gcwrapper.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/memory/gcwrapper.py Mon May 5 21:56:10 2008 @@ -114,9 +114,6 @@ def __init__(self, gcheap): self.gcheap = gcheap - def append_static_root(self, pointer): - self.gcheap.constantroots.append(pointer) - def walk_roots(self, collect_stack_root, collect_static_in_prebuilt_nongc, collect_static_in_prebuilt_gc): From arigo at codespeak.net Mon May 5 22:20:24 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 5 May 2008 22:20:24 +0200 (CEST) Subject: [pypy-svn] r54451 - pypy/branch/gc-tweak/pypy/rpython/memory/test Message-ID: <20080505202024.327DB168457@codespeak.net> Author: arigo Date: Mon May 5 22:20:23 2008 New Revision: 54451 Modified: pypy/branch/gc-tweak/pypy/rpython/memory/test/test_transformed_gc.py Log: Fix test. Modified: pypy/branch/gc-tweak/pypy/rpython/memory/test/test_transformed_gc.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/memory/test/test_transformed_gc.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/memory/test/test_transformed_gc.py Mon May 5 22:20:23 2008 @@ -855,9 +855,11 @@ run, transformer = self.runner(f, nbargs=2, transformer=True) run([1, 4]) - assert len(transformer.layoutbuilder.addresses_of_static_ptrs) == 0 - assert transformer.layoutbuilder.additional_roots_sources >= 4 - # NB. Remember that additional_roots_sources does not count + if not transformer.GCClass.prebuilt_gc_objects_are_static_roots: + assert len(transformer.layoutbuilder.addresses_of_static_ptrs) == 0 + else: + assert len(transformer.layoutbuilder.addresses_of_static_ptrs) >= 4 + # NB. Remember that the number above does not count # the number of prebuilt GC objects, but the number of locations # within prebuilt GC objects that are of type Ptr(Gc). # At the moment we get additional_roots_sources == 6: From arigo at codespeak.net Mon May 5 23:44:37 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 5 May 2008 23:44:37 +0200 (CEST) Subject: [pypy-svn] r54453 - pypy/branch/gc-tweak/pypy/rpython/memory/gc Message-ID: <20080505214437.5AFF516844A@codespeak.net> Author: arigo Date: Mon May 5 23:44:35 2008 New Revision: 54453 Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gc/semispace.py Log: Turn DEBUG_PRINT off again. Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gc/semispace.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/memory/gc/semispace.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/memory/gc/semispace.py Mon May 5 23:44:35 2008 @@ -21,7 +21,7 @@ GCFLAG_EXTERNAL = first_gcflag << 1 GCFLAG_FINALIZATION_ORDERING = first_gcflag << 2 -DEBUG_PRINT = True +DEBUG_PRINT = False memoryError = MemoryError() class SemiSpaceGC(MovingGCBase): From arigo at codespeak.net Tue May 6 10:41:04 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 6 May 2008 10:41:04 +0200 (CEST) Subject: [pypy-svn] r54471 - pypy/dist/pypy/translator/benchmark Message-ID: <20080506084104.9520E16841D@codespeak.net> Author: arigo Date: Tue May 6 10:41:03 2008 New Revision: 54471 Modified: pypy/dist/pypy/translator/benchmark/benchmarks.py Log: Test runner updated, so bench-custom needs a fresh checkout of gadfly. Modified: pypy/dist/pypy/translator/benchmark/benchmarks.py ============================================================================== --- pypy/dist/pypy/translator/benchmark/benchmarks.py (original) +++ pypy/dist/pypy/translator/benchmark/benchmarks.py Tue May 6 10:41:03 2008 @@ -162,7 +162,7 @@ def check_gadfly(): return external_dependency('gadfly', 'http://codespeak.net/svn/user/arigo/hack/pypy-hack/gadflyZip', - 40406) + 54470) def run_mako(executable='/usr/local/bin/python'): """ run some tests in the mako templating system """ From cami at codespeak.net Tue May 6 12:10:54 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Tue, 6 May 2008 12:10:54 +0200 (CEST) Subject: [pypy-svn] r54472 - in pypy/branch/gameboy-emulator/pypy/lang: gameboy test Message-ID: <20080506101054.32E5516842E@codespeak.net> Author: cami Date: Tue May 6 12:10:52 2008 New Revision: 54472 Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py pypy/branch/gameboy-emulator/pypy/lang/test/test_translation.py Log: changed changes back for register inheritence Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py Tue May 6 12:10:52 2008 @@ -27,7 +27,7 @@ # ------------------------------------------------------------------------------ -class DoubleRegister(Register): +class DoubleRegister(object): def __init__(self, cpu, hi=None, lo=None, resetValue=0): self.cpu = cpu @@ -42,7 +42,7 @@ self.resetValue = resetValue def set(self, hi=0, lo=None, useCycles=True): - if (lo is None): + if lo is None: self.setHi(hi >> 8, useCycles) self.setLo(hi & 0xFF, useCycles) if useCycles: @@ -52,7 +52,7 @@ self.setLo(lo, useCycles) def reset(self): - self.set(self.resetValue, None, useCycles=False) + self.set(self.resetValue, useCycles=False) def setHi(self, hi=0, useCycles=True): self.hi.set(hi, useCycles) @@ -70,17 +70,17 @@ return self.lo.get(useCycles) def inc(self, useCycles=True): - self.set(self.get(useCycles) +1, None, useCycles) + self.set(self.get(useCycles) +1, useCycles=useCycles) if useCycles: self.cpu.cycles -= 1 def dec(self, useCycles=True): - self.set(self.get(useCycles) - 1, None, useCycles) + self.set(self.get(useCycles) - 1, useCycles=useCycles) if useCycles: self.cpu.cycles -= 1 def add(self, n=2, useCycles=True): - self.set(self.get(useCycles) + n, None, useCycles) + self.set(self.get(useCycles) + n, useCycles=useCycles) if useCycles: self.cpu.cycles -= 2 @@ -92,18 +92,18 @@ self.hl = hl def set(self, value, useCycles=True): - self.cpu.write(self.hl.get(useCycles), value) # 2 + 0 + self.cpu.write(self.hl.get(useCycles=useCycles), value) # 2 + 0 if not useCycles: self.cpu.cycles += 2 def get(self, useCycles=True): if not useCycles: self.cpu.cycles += 1 - return self.cpu.read(self.hl.get(useCycles)) # 1 + return self.cpu.read(self.hl.get(useCycles=useCycles)) # 1 # ------------------------------------------------------------------------------ -class FlagRegister(Register): +class FlagRegister(object): def __init__(self, cpu): self.cpu = cpu @@ -156,18 +156,10 @@ self.cFlag = True def hFlagCompare(self, a, b): - if isinstance(a, (Register)): - a = a.get() - if isinstance(b, (Register)): - b = b.get() if (a & 0x0F) < (b & 0x0F): self.hFlag = True def cFlagCompare(self, a, b): - if isinstance(a, (Register)): - a = a.get() - if isinstance(b, (Register)): - b = b.get() if a < b: self.cFlag = True @@ -411,7 +403,7 @@ # 4 cycles self.push(self.pc.getHi(useCycles), useCycles) # 2 cycles self.push(self.pc.getLo(useCycles), useCycles) # 2 cycles - self.pc.set(address, None, useCycles) # 1 cycle + self.pc.set(address, useCycles=useCycles) # 1 cycle if useCycles: self.cycles += 1 @@ -433,16 +425,17 @@ # ALU, 1 cycle added = (self.a.get() + getter()) & 0xFF self.f.zFlagCompare(added, reset=True) - self.f.hFlagCompare(added, self.a) - self.f.cFlagCompare(added, self.a) + self.f.hFlagCompare(added, self.a.get()) + self.f.cFlagCompare(added, self.a.get()) self.a.set(added) # 1 cycle def addHL(self, register): # 2 cycles + a=1 added = (self.hl.get() + register.get()) & 0xFFFF # 1 cycle self.f.reset(keepZ=True) - self.f.hFlagCompare((added >> 8), self.hl) - self.f.cFlagCompare(added, self.hl) + self.f.hFlagCompare((added >> 8), self.hl.get()) + self.f.cFlagCompare(added, self.hl.get()) self.hl.set(added) self.cycles -= 1 @@ -494,22 +487,22 @@ def hcFlagFinish(self, data): if data > self.a.get(): self.f.cFlag = True - self.f.hFlagCompare(self.a, data) + self.f.hFlagCompare(self.a.get(), data) def AND(self, getter, setter=None): # 1 cycle self.a.set(self.a.get() & getter()) # 1 cycle - self.f.zFlagCompare(self.a, reset=True) + self.f.zFlagCompare(self.a.get(), reset=True) def XOR(self, getter, setter=None): # 1 cycle self.a.set( self.a.get() ^ getter()) # 1 cycle - self.f.zFlagCompare(self.a, reset=True) + self.f.zFlagCompare(self.a.get(), reset=True) def OR(self, getter, setter=None): # 1 cycle self.a.set(self.a.get() | getter()) # 1 cycle - self.f.zFlagCompare(self.a, reset=True) + self.f.zFlagCompare(self.a.get(), reset=True) def incDoubleRegister(self, doubleRegister): doubleRegister.inc() @@ -728,7 +721,7 @@ self.f.reset(keepN=True) if delta >= 0x60: self.f.cFlag = True - self.f.zFlagCompare(self.a) + self.f.zFlagCompare(self.a.get()) def incDoubleRegister(self, register): # INC rr Modified: pypy/branch/gameboy-emulator/pypy/lang/test/test_translation.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/test/test_translation.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/test/test_translation.py Tue May 6 12:10:52 2008 @@ -24,11 +24,14 @@ drv.exe_name = None drv.proceed('compile') - def test_scheme(self): - self.translate('targetscheme') + #def test_scheme(self): + # self.translate('targetscheme') - def test_js(self): - self.translate('targetjsstandalone') + #def test_js(self): + # self.translate('targetjsstandalone') - def test_prolog(self): - self.translate('targetprologstandalone') + #def test_prolog(self): + # self.translate('targetprologstandalone') + + def test_gameboy(self): + self.translate('targetgameboytest') From antocuni at codespeak.net Tue May 6 14:10:34 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 6 May 2008 14:10:34 +0200 (CEST) Subject: [pypy-svn] r54473 - pypy/dist/pypy/lib/_ctypes Message-ID: <20080506121034.91E621683F8@codespeak.net> Author: antocuni Date: Tue May 6 14:10:31 2008 New Revision: 54473 Modified: pypy/dist/pypy/lib/_ctypes/pointer.py Log: allow None as a null pointer value for _cast_addr (test following) Modified: pypy/dist/pypy/lib/_ctypes/pointer.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/pointer.py (original) +++ pypy/dist/pypy/lib/_ctypes/pointer.py Tue May 6 14:10:31 2008 @@ -119,6 +119,9 @@ result = tp() result._buffer[0] = obj return result + if obj is None: + result = tp() + return result if not (isinstance(obj, _CData) and type(obj)._is_pointer_like()): raise TypeError("cast() argument 1 must be a pointer, not %s" % (type(obj),)) From arigo at codespeak.net Tue May 6 14:21:44 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 6 May 2008 14:21:44 +0200 (CEST) Subject: [pypy-svn] r54474 - pypy/dist/pypy/lib/app_test/ctypes_tests Message-ID: <20080506122144.2DC1D168413@codespeak.net> Author: arigo Date: Tue May 6 14:21:43 2008 New Revision: 54474 Modified: pypy/dist/pypy/lib/app_test/ctypes_tests/test_extra.py Log: Test for r54473. Modified: pypy/dist/pypy/lib/app_test/ctypes_tests/test_extra.py ============================================================================== --- pypy/dist/pypy/lib/app_test/ctypes_tests/test_extra.py (original) +++ pypy/dist/pypy/lib/app_test/ctypes_tests/test_extra.py Tue May 6 14:21:43 2008 @@ -228,3 +228,13 @@ def test_from_param(self): # other working cases of from_param assert isinstance(c_void_p.from_param((c_int * 4)()), c_int*4) + + def test_cast_none(self): + def check(P): + x = cast(None, P) + assert isinstance(x, P) + assert not x + check(c_void_p) + check(c_char_p) + check(POINTER(c_int)) + check(POINTER(c_int * 10)) From arigo at codespeak.net Tue May 6 14:25:06 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 6 May 2008 14:25:06 +0200 (CEST) Subject: [pypy-svn] r54475 - in pypy/dist/pypy/lib: _ctypes app_test/ctypes_tests Message-ID: <20080506122506.35701168420@codespeak.net> Author: arigo Date: Tue May 6 14:25:05 2008 New Revision: 54475 Modified: pypy/dist/pypy/lib/_ctypes/array.py pypy/dist/pypy/lib/_ctypes/basics.py pypy/dist/pypy/lib/app_test/ctypes_tests/test_extra.py Log: Trivial fixes to "ctype * integer" variants. Modified: pypy/dist/pypy/lib/_ctypes/array.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/array.py (original) +++ pypy/dist/pypy/lib/_ctypes/array.py Tue May 6 14:25:05 2008 @@ -191,6 +191,8 @@ ARRAY_CACHE = {} def create_array_type(base, length): + if not isinstance(length, (int, long)): + raise TypeError("Can't multiply a ctypes type by a non-integer") if length < 0: raise ValueError("Array length must be >= 0") key = (base, length) Modified: pypy/dist/pypy/lib/_ctypes/basics.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/basics.py (original) +++ pypy/dist/pypy/lib/_ctypes/basics.py Tue May 6 14:25:05 2008 @@ -72,6 +72,8 @@ from _ctypes.array import create_array_type return create_array_type(self, other) + __rmul__ = __mul__ + def _is_pointer_like(self): return False Modified: pypy/dist/pypy/lib/app_test/ctypes_tests/test_extra.py ============================================================================== --- pypy/dist/pypy/lib/app_test/ctypes_tests/test_extra.py (original) +++ pypy/dist/pypy/lib/app_test/ctypes_tests/test_extra.py Tue May 6 14:25:05 2008 @@ -229,6 +229,14 @@ # other working cases of from_param assert isinstance(c_void_p.from_param((c_int * 4)()), c_int*4) + def test_array_mul(self): + assert c_int * 10 == 10 * c_int == c_int * 10L == 10L * c_int + py.test.raises(TypeError, 'c_int * c_int') + py.test.raises(TypeError, 'c_int * (-1.5)') + py.test.raises(TypeError, 'c_int * "foo"') + py.test.raises(TypeError, '(-1.5) * c_int') + py.test.raises(TypeError, '"foo" * c_int') + def test_cast_none(self): def check(P): x = cast(None, P) From antocuni at codespeak.net Tue May 6 15:13:29 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 6 May 2008 15:13:29 +0200 (CEST) Subject: [pypy-svn] r54476 - in pypy/extradoc/talk/pycon-italy-2008: . ui Message-ID: <20080506131329.A77FC1683D9@codespeak.net> Author: antocuni Date: Tue May 6 15:13:27 2008 New Revision: 54476 Added: pypy/extradoc/talk/pycon-italy-2008/motivation.txt - copied, changed from r53167, pypy/extradoc/talk/roadshow-google/motivation.txt pypy/extradoc/talk/pycon-italy-2008/overview1.png - copied unchanged from r53167, pypy/extradoc/talk/roadshow-google/overview1.png pypy/extradoc/talk/pycon-italy-2008/overview2.png - copied unchanged from r53167, pypy/extradoc/talk/roadshow-google/overview2.png pypy/extradoc/talk/pycon-italy-2008/technical.txt - copied unchanged from r53167, pypy/extradoc/talk/roadshow-google/technical.txt pypy/extradoc/talk/pycon-italy-2008/ui/ - copied from r53167, pypy/extradoc/talk/roadshow-google/ui/ Log: early draft of my talk, mostly copied from the google roadshow From arigo at codespeak.net Tue May 6 15:24:58 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 6 May 2008 15:24:58 +0200 (CEST) Subject: [pypy-svn] r54477 - in pypy/branch/gc-tweak/pypy/rpython/memory: . gc Message-ID: <20080506132458.6E27916842C@codespeak.net> Author: arigo Date: Tue May 6 15:24:58 2008 New Revision: 54477 Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gc/base.py pypy/branch/gc-tweak/pypy/rpython/memory/gc/generation.py pypy/branch/gc-tweak/pypy/rpython/memory/gc/hybrid.py pypy/branch/gc-tweak/pypy/rpython/memory/gc/semispace.py pypy/branch/gc-tweak/pypy/rpython/memory/gcwrapper.py Log: While running test_gc, add an explicit check before and after minor and major collections which verifies the global consistency of the objects. Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gc/base.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/memory/gc/base.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/memory/gc/base.py Tue May 6 15:24:58 2008 @@ -7,6 +7,7 @@ needs_write_barrier = False malloc_zero_filled = False prebuilt_gc_objects_are_static_roots = True + DEBUG = False # set to True for test_gc.py def set_query_functions(self, is_varsize, has_gcptr_in_varsize, is_gcarrayofgcptr, @@ -148,6 +149,38 @@ length -= 1 trace._annspecialcase_ = 'specialize:arg(2)' + def debug_check_consistency(self): + """To use around a collection. If self.DEBUG is set, this + enumerates all roots and trace all objects to check if we didn't + accidentally free a reachable object or forgot to update a pointer + to an object that moved. + """ + if self.DEBUG: + # this part is not rpython + seen = {} + pending = [] + + def record(obj): + hdrobj = self.header(obj)._obj + if hdrobj not in seen: + seen[hdrobj] = True + pending.append(obj) + + def callback(self, root): + obj = root.address[0] + assert obj + record(obj) + + def callback2(pointer, ignored): + obj = pointer.address[0] + if obj: + record(obj) + + self.root_walker.walk_roots(callback, callback, callback) + while pending: + obj = pending.pop() + self.trace(obj, callback2, None) + class MovingGCBase(GCBase): moving_gc = True Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gc/generation.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/memory/gc/generation.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/memory/gc/generation.py Tue May 6 15:24:58 2008 @@ -321,6 +321,7 @@ ll_assert(self.nursery_size <= self.top_of_space - self.free, "obtain_free_space failed to do its job") if self.nursery: + self.debug_check_consistency() if DEBUG_PRINT: llop.debug_print(lltype.Void, "minor collect") # a nursery-only collection @@ -337,6 +338,7 @@ llarena.arena_reset(self.nursery, self.nursery_size, True) if DEBUG_PRINT: llop.debug_print(lltype.Void, "percent survived:", float(scan - beginning) / self.nursery_size) + self.debug_check_consistency() else: # no nursery - this occurs after a full collect, triggered either # just above or by some previous non-nursery-based allocation. Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gc/hybrid.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/memory/gc/hybrid.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/memory/gc/hybrid.py Tue May 6 15:24:58 2008 @@ -264,6 +264,12 @@ # At the start of a collection, the GCFLAG_UNVISITED bit is set # exactly on the objects in gen2_rawmalloced_objects. Only # raw_malloc'ed objects can ever have this bit set. + if self.DEBUG: + def check_bit(obj, expected): + assert self.header(obj).tid & GCFLAG_UNVISITED == expected + self.gen2_rawmalloced_objects.foreach(check_bit, GCFLAG_UNVISITED) + self.gen3_rawmalloced_objects.foreach(check_bit, 0) + self.count_semispaceonly_collects += 1 if self.is_collecting_gen3(): # set the GCFLAG_UNVISITED on all rawmalloced generation-3 objects Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gc/semispace.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/memory/gc/semispace.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/memory/gc/semispace.py Tue May 6 15:24:58 2008 @@ -208,6 +208,7 @@ # (this is also a hook for the HybridGC) def semispace_collect(self, size_changing=False): + self.debug_check_consistency() if DEBUG_PRINT: import time llop.debug_print(lltype.Void) @@ -235,6 +236,7 @@ if self.objects_with_weakrefs.non_empty(): self.invalidate_weakrefs() self.finished_full_collect() + self.debug_check_consistency() self.notify_objects_just_moved() if not size_changing: llarena.arena_reset(fromspace, self.space_size, True) Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gcwrapper.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/memory/gcwrapper.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/memory/gcwrapper.py Tue May 6 15:24:58 2008 @@ -10,6 +10,7 @@ def __init__(self, llinterp, flowgraphs, gc_class, GC_PARAMS={}): self.gc = gc_class(chunk_size = 10, **GC_PARAMS) self.gc.set_root_walker(LLInterpRootWalker(self)) + self.gc.DEBUG = True self.llinterp = llinterp self.prepare_graphs(flowgraphs) self.gc.setup() From antocuni at codespeak.net Tue May 6 15:45:20 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 6 May 2008 15:45:20 +0200 (CEST) Subject: [pypy-svn] r54478 - pypy/extradoc/talk/pycon-italy-2008 Message-ID: <20080506134520.D1E9616840C@codespeak.net> Author: antocuni Date: Tue May 6 15:45:18 2008 New Revision: 54478 Modified: pypy/extradoc/talk/pycon-italy-2008/motivation.txt pypy/extradoc/talk/pycon-italy-2008/overview1.png pypy/extradoc/talk/pycon-italy-2008/overview2.png Log: split status update into 2 slides, modify the images Modified: pypy/extradoc/talk/pycon-italy-2008/motivation.txt ============================================================================== --- pypy/extradoc/talk/pycon-italy-2008/motivation.txt (original) +++ pypy/extradoc/talk/pycon-italy-2008/motivation.txt Tue May 6 15:45:18 2008 @@ -34,28 +34,32 @@ * (demo) -PyPy status update -================== +PyPy status update (1) +====================== + +- JVM backend completed, pypy-jvm + +- some new GCs, much faster than ever -What happened in the last year: +- ctypes for PyPy - - JVM backend completed, pypy-jvm +- JIT refactoring, needed to make the JIT production-ready - - some new GCs, much faster than ever; e.g., generational GC +- improved .NET integration for pypy-cli - - ctypes for PyPy +- new blog: http://morepypy.blogspot.com - - various performance improvements - * as fast as CPython on pystone +PyPy status update (2) +====================== - * slighly faster on richards +- various performance improvements - * less than 2x slower on other benchmarks +- slighly slower than CPython on pystone (10-20%) - - JIT refactoring, needed to make the JIT production-ready +- but faster on richards (20-24%) - - improved .NET integration for pypy-cli +- less than 2x slower on other benchmarks Interpreters @@ -232,14 +236,12 @@ pypy-c-jit ====================== -.. where to put this? - PyPy 1.0 contains both the dynamic compiler generator and the start of its application to PyPy's Python intepreter. +JIT refactoring in-progress. + * included are backends for IA32 and PPC +* experimental/incomplete CLI backend * integer arithmetic operations are optimized * for these, we are in the speed range of ``gcc -O0`` -* demo (63x faster than CPython) - -.. demo f1 Modified: pypy/extradoc/talk/pycon-italy-2008/overview1.png ============================================================================== Binary files. No diff available. Modified: pypy/extradoc/talk/pycon-italy-2008/overview2.png ============================================================================== Binary files. No diff available. From arigo at codespeak.net Tue May 6 16:39:34 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 6 May 2008 16:39:34 +0200 (CEST) Subject: [pypy-svn] r54479 - in pypy/branch/gc-tweak/pypy/rpython/memory: . gc Message-ID: <20080506143934.CDA9716842B@codespeak.net> Author: arigo Date: Tue May 6 16:39:32 2008 New Revision: 54479 Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gc/base.py pypy/branch/gc-tweak/pypy/rpython/memory/gc/generation.py pypy/branch/gc-tweak/pypy/rpython/memory/gc/hybrid.py pypy/branch/gc-tweak/pypy/rpython/memory/gc/semispace.py pypy/branch/gc-tweak/pypy/rpython/memory/gctypelayout.py pypy/branch/gc-tweak/pypy/rpython/memory/gcwrapper.py Log: Try to cover as many invariants as possible in the debug checks. Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gc/base.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/memory/gc/base.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/memory/gc/base.py Tue May 6 16:39:32 2008 @@ -150,7 +150,7 @@ trace._annspecialcase_ = 'specialize:arg(2)' def debug_check_consistency(self): - """To use around a collection. If self.DEBUG is set, this + """To use after a collection. If self.DEBUG is set, this enumerates all roots and trace all objects to check if we didn't accidentally free a reachable object or forgot to update a pointer to an object that moved. @@ -176,11 +176,16 @@ if obj: record(obj) - self.root_walker.walk_roots(callback, callback, callback) + self.root_walker._walk_prebuilt_gc(record) + self.root_walker.walk_roots(callback, callback, None) while pending: obj = pending.pop() + self.debug_check_object(obj) self.trace(obj, callback2, None) + def debug_check_object(self, obj): + pass + class MovingGCBase(GCBase): moving_gc = True Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gc/generation.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/memory/gc/generation.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/memory/gc/generation.py Tue May 6 16:39:32 2008 @@ -321,7 +321,6 @@ ll_assert(self.nursery_size <= self.top_of_space - self.free, "obtain_free_space failed to do its job") if self.nursery: - self.debug_check_consistency() if DEBUG_PRINT: llop.debug_print(lltype.Void, "minor collect") # a nursery-only collection @@ -444,6 +443,48 @@ # overridden by HybridGC return (self.header(obj).tid & GCFLAG_EXTERNAL) != 0 + def debug_check_object(self, obj): + """Check the invariants about 'obj' that should be true + between collections.""" + SemiSpaceGC.debug_check_object(self, obj) + tid = self.header(obj).tid + if tid & GCFLAG_NO_YOUNG_PTRS: + def _no_nursery_pointer(root, ignored): + assert not self.is_in_nursery(root.address[0]) + assert not self.is_in_nursery(obj) + self.trace(obj, _no_nursery_pointer, None) + elif not self.is_in_nursery(obj): + assert self.header(obj)._obj in self._d_oopty + if tid & GCFLAG_NO_HEAP_PTRS: + def _no_gen1or2_pointer(root, ignored): + target = root.address[0] + assert not target or self.is_last_generation(target) + assert self.is_last_generation(obj) + self.trace(obj, _no_gen1or2_pointer, None) + elif self.is_last_generation(obj): + assert self.header(obj)._obj in self._d_lgro + + def debug_check_consistency(self): + if self.DEBUG: + self._make_dict("old_objects_pointing_to_young", "_d_oopty") + self._make_dict("last_generation_root_objects", "_d_lgro") + SemiSpaceGC.debug_check_consistency(self) + def check1(obj, ignored): + assert not (self.header(obj).tid & GCFLAG_NO_YOUNG_PTRS) + def check2(obj, ignored): + assert not (self.header(obj).tid & GCFLAG_NO_HEAP_PTRS) + self.old_objects_pointing_to_young.foreach(check1, None) + self.last_generation_root_objects.foreach(check2, None) + + def _make_dict(self, attr, shortattr): + result = {} + def _add_dict(obj, ignored): + hdrobj = self.header(obj)._obj + result[hdrobj] = True + lst = getattr(self, attr) + lst.foreach(_add_dict, None) + setattr(self, shortattr, result) + # ____________________________________________________________ import os Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gc/hybrid.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/memory/gc/hybrid.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/memory/gc/hybrid.py Tue May 6 16:39:32 2008 @@ -264,12 +264,6 @@ # At the start of a collection, the GCFLAG_UNVISITED bit is set # exactly on the objects in gen2_rawmalloced_objects. Only # raw_malloc'ed objects can ever have this bit set. - if self.DEBUG: - def check_bit(obj, expected): - assert self.header(obj).tid & GCFLAG_UNVISITED == expected - self.gen2_rawmalloced_objects.foreach(check_bit, GCFLAG_UNVISITED) - self.gen3_rawmalloced_objects.foreach(check_bit, 0) - self.count_semispaceonly_collects += 1 if self.is_collecting_gen3(): # set the GCFLAG_UNVISITED on all rawmalloced generation-3 objects @@ -469,3 +463,28 @@ "nonmoving freed: ", dead_size, "bytes in", dead_count, "objs") + + def debug_check_object(self, obj): + """Check the invariants about 'obj' that should be true + between collections.""" + GenerationGC.debug_check_object(self, obj) + tid = self.header(obj).tid + if tid & GCFLAG_UNVISITED: + assert self.header(obj)._obj in self._d_gen2ro + + def debug_check_consistency(self): + if self.DEBUG: + self._make_dict("gen2_rawmalloced_objects", "_d_gen2ro") + GenerationGC.debug_check_consistency(self) + def check_gen2(obj, ignored): + tid = self.header(obj).tid + assert tid & GCFLAG_EXTERNAL + assert tid & GCFLAG_UNVISITED + assert (tid & GCFLAG_AGE_MASK) < GCFLAG_AGE_MAX + def check_gen3(obj, ignored): + tid = self.header(obj).tid + assert tid & GCFLAG_EXTERNAL + assert not (tid & GCFLAG_UNVISITED) + assert (tid & GCFLAG_AGE_MASK) == GCFLAG_AGE_MAX + self.gen2_rawmalloced_objects.foreach(check_gen2, None) + self.gen3_rawmalloced_objects.foreach(check_gen3, None) Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gc/semispace.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/memory/gc/semispace.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/memory/gc/semispace.py Tue May 6 16:39:32 2008 @@ -202,13 +202,13 @@ self.max_space_size = size def collect(self): + self.debug_check_consistency() self.semispace_collect() # the indirection is required by the fact that collect() is referred # to by the gc transformer, and the default argument would crash # (this is also a hook for the HybridGC) def semispace_collect(self, size_changing=False): - self.debug_check_consistency() if DEBUG_PRINT: import time llop.debug_print(lltype.Void) @@ -571,5 +571,14 @@ finally: self.finalizer_lock_count -= 1 + def debug_check_object(self, obj): + """Check the invariants about 'obj' that should be true + between collections.""" + tid = self.header(obj).tid + if not (tid & GCFLAG_EXTERNAL): + assert not (tid & GCFLAG_FORWARDED) + assert (self.tospace <= obj < self.free) == (not (tid&GCFLAG_EXTERNAL)) + assert not (tid & GCFLAG_FINALIZATION_ORDERING) + STATISTICS_NUMBERS = 0 Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gctypelayout.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/memory/gctypelayout.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/memory/gctypelayout.py Tue May 6 16:39:32 2008 @@ -193,6 +193,9 @@ self.addresses_of_static_ptrs = [] # this lists contains pointers in raw Structs and Arrays self.addresses_of_static_ptrs_in_nongc = [] + # for debugging, the following list collects all the prebuilt + # GcStructs and GcArrays + self.all_prebuilt_gc = [] self.finalizer_funcptrs = {} self.offsettable_cache = {} self.next_typeid_cache = {} @@ -280,6 +283,7 @@ hdr = gc.gcheaderbuilder.new_header(value) adr = llmemory.cast_ptr_to_adr(hdr) gc.init_gc_object_immortal(adr, typeid) + self.all_prebuilt_gc.append(value) # The following collects the addresses of all the fields that have # a GC Pointer type, inside the current prebuilt object. All such Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gcwrapper.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/memory/gcwrapper.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/memory/gcwrapper.py Tue May 6 16:39:32 2008 @@ -25,8 +25,9 @@ TYPE = lltype.typeOf(obj) layoutbuilder.consider_constant(TYPE, obj, self.gc) - self.constantroots = list(layoutbuilder.addresses_of_static_ptrs) + self.constantroots = layoutbuilder.addresses_of_static_ptrs self.constantrootsnongc = layoutbuilder.addresses_of_static_ptrs_in_nongc + self._all_prebuilt_gc = layoutbuilder.all_prebuilt_gc # ____________________________________________________________ # @@ -133,6 +134,10 @@ if addrofaddr.address[0]: collect_stack_root(gc, addrofaddr) + def _walk_prebuilt_gc(self, collect): # debugging only! not RPython + for obj in self.gcheap._all_prebuilt_gc: + collect(llmemory.cast_ptr_to_adr(obj._as_ptr())) + class DirectRunLayoutBuilder(gctypelayout.TypeLayoutBuilder): From arigo at codespeak.net Tue May 6 16:53:52 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 6 May 2008 16:53:52 +0200 (CEST) Subject: [pypy-svn] r54480 - pypy/branch/gc-tweak/pypy/rpython/memory/test Message-ID: <20080506145352.82E911683E9@codespeak.net> Author: arigo Date: Tue May 6 16:53:52 2008 New Revision: 54480 Modified: pypy/branch/gc-tweak/pypy/rpython/memory/test/test_transformed_gc.py Log: Another passing test... Modified: pypy/branch/gc-tweak/pypy/rpython/memory/test/test_transformed_gc.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/memory/test/test_transformed_gc.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/memory/test/test_transformed_gc.py Tue May 6 16:53:52 2008 @@ -919,3 +919,25 @@ 'nursery_size': 128, 'large_object': 32} root_stack_depth = 200 + + def test_ref_from_rawmalloced_to_regular(self): + import gc + S = lltype.GcStruct('S', ('x', lltype.Signed)) + A = lltype.GcStruct('A', ('p', lltype.Ptr(S)), + ('a', lltype.Array(lltype.Char))) + def setup(j): + p = lltype.malloc(S) + p.x = j*2 + lst = lltype.malloc(A, j) + # the following line generates a write_barrier call at the moment, + # which is important because the 'lst' can be allocated directly + # in generation 2. This can only occur with varsized mallocs. + lst.p = p + return lst + def f(i, j): + lst = setup(j) + gc.collect() + return lst.p.x + run = self.runner(f, nbargs=2) + res = run([100, 100]) + assert res == 200 From arigo at codespeak.net Tue May 6 18:30:34 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 6 May 2008 18:30:34 +0200 (CEST) Subject: [pypy-svn] r54483 - in pypy/branch/gc-tweak/pypy/rpython/memory: . gc Message-ID: <20080506163034.AD8E916840E@codespeak.net> Author: arigo Date: Tue May 6 18:30:34 2008 New Revision: 54483 Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gc/base.py pypy/branch/gc-tweak/pypy/rpython/memory/gc/generation.py pypy/branch/gc-tweak/pypy/rpython/memory/gc/hybrid.py pypy/branch/gc-tweak/pypy/rpython/memory/gc/semispace.py pypy/branch/gc-tweak/pypy/rpython/memory/gctypelayout.py pypy/branch/gc-tweak/pypy/rpython/memory/support.py Log: Make the consistency checking logic RPython. Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gc/base.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/memory/gc/base.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/memory/gc/base.py Tue May 6 18:30:34 2008 @@ -7,7 +7,12 @@ needs_write_barrier = False malloc_zero_filled = False prebuilt_gc_objects_are_static_roots = True - DEBUG = False # set to True for test_gc.py + + # The following flag enables costly consistency checks after each + # collection. It is automatically set to True by test_gc.py. The + # checking logic is translatable, so the flag can be set to True + # here before translation. + DEBUG = False def set_query_functions(self, is_varsize, has_gcptr_in_varsize, is_gcarrayofgcptr, @@ -151,37 +156,37 @@ def debug_check_consistency(self): """To use after a collection. If self.DEBUG is set, this - enumerates all roots and trace all objects to check if we didn't + enumerates all roots and traces all objects to check if we didn't accidentally free a reachable object or forgot to update a pointer to an object that moved. """ if self.DEBUG: - # this part is not rpython - seen = {} - pending = [] - - def record(obj): - hdrobj = self.header(obj)._obj - if hdrobj not in seen: - seen[hdrobj] = True - pending.append(obj) - - def callback(self, root): - obj = root.address[0] - assert obj - record(obj) - - def callback2(pointer, ignored): - obj = pointer.address[0] - if obj: - record(obj) - - self.root_walker._walk_prebuilt_gc(record) - self.root_walker.walk_roots(callback, callback, None) - while pending: + from pypy.rlib.objectmodel import we_are_translated + self._debug_seen = self.AddressStack() + self._debug_pending = self.AddressStack() + if not we_are_translated(): + self.root_walker._walk_prebuilt_gc(self._debug_record) + callback = GCBase._debug_callback + self.root_walker.walk_roots(callback, callback, callback) + pending = self._debug_pending + while pending.non_empty(): obj = pending.pop() self.debug_check_object(obj) - self.trace(obj, callback2, None) + self.trace(obj, self._debug_callback2, None) + + def _debug_record(self, obj): + seen = self._debug_seen + if not seen.contains(obj): + seen.append(obj) + self._debug_pending.append(obj) + def _debug_callback(self, root): + obj = root.address[0] + ll_assert(bool(obj), "NULL address from walk_roots()") + self._debug_record(obj) + def _debug_callback2(self, pointer, ignored): + obj = pointer.address[0] + if obj: + self._debug_record(obj) def debug_check_object(self, obj): pass Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gc/generation.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/memory/gc/generation.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/memory/gc/generation.py Tue May 6 18:30:34 2008 @@ -449,41 +449,42 @@ SemiSpaceGC.debug_check_object(self, obj) tid = self.header(obj).tid if tid & GCFLAG_NO_YOUNG_PTRS: - def _no_nursery_pointer(root, ignored): - assert not self.is_in_nursery(root.address[0]) - assert not self.is_in_nursery(obj) - self.trace(obj, _no_nursery_pointer, None) + ll_assert(not self.is_in_nursery(obj), + "nursery object with GCFLAG_NO_YOUNG_PTRS") + self.trace(obj, self._debug_no_nursery_pointer, None) elif not self.is_in_nursery(obj): - assert self.header(obj)._obj in self._d_oopty + ll_assert(self.old_objects_pointing_to_young.contains(obj), + "missing from old_objects_pointing_to_young") if tid & GCFLAG_NO_HEAP_PTRS: - def _no_gen1or2_pointer(root, ignored): - target = root.address[0] - assert not target or self.is_last_generation(target) - assert self.is_last_generation(obj) - self.trace(obj, _no_gen1or2_pointer, None) + ll_assert(self.is_last_generation(obj), + "GCFLAG_NO_HEAP_PTRS on non-3rd-generation object") + self.trace(obj, self._debug_no_gen1or2_pointer, None) elif self.is_last_generation(obj): - assert self.header(obj)._obj in self._d_lgro + ll_assert(self.last_generation_root_objects.contains(obj), + "missing from last_generation_root_objects") + + def _debug_no_nursery_pointer(self, root, ignored): + ll_assert(not self.is_in_nursery(root.address[0]), + "GCFLAG_NO_YOUNG_PTRS but found a young pointer") + def _debug_no_gen1or2_pointer(self, root, ignored): + target = root.address[0] + ll_assert(not target or self.is_last_generation(target), + "GCFLAG_NO_HEAP_PTRS but found a pointer to gen1or2") def debug_check_consistency(self): if self.DEBUG: - self._make_dict("old_objects_pointing_to_young", "_d_oopty") - self._make_dict("last_generation_root_objects", "_d_lgro") SemiSpaceGC.debug_check_consistency(self) - def check1(obj, ignored): - assert not (self.header(obj).tid & GCFLAG_NO_YOUNG_PTRS) - def check2(obj, ignored): - assert not (self.header(obj).tid & GCFLAG_NO_HEAP_PTRS) - self.old_objects_pointing_to_young.foreach(check1, None) - self.last_generation_root_objects.foreach(check2, None) - - def _make_dict(self, attr, shortattr): - result = {} - def _add_dict(obj, ignored): - hdrobj = self.header(obj)._obj - result[hdrobj] = True - lst = getattr(self, attr) - lst.foreach(_add_dict, None) - setattr(self, shortattr, result) + self.old_objects_pointing_to_young.foreach( + self._debug_check_flag_1, None) + self.last_generation_root_objects.foreach( + self._debug_check_flag_2, None) + + def _debug_check_flag_1(self, obj, ignored): + ll_assert(not (self.header(obj).tid & GCFLAG_NO_YOUNG_PTRS), + "unexpected GCFLAG_NO_YOUNG_PTRS") + def _debug_check_flag_2(self, obj, ignored): + ll_assert(not (self.header(obj).tid & GCFLAG_NO_HEAP_PTRS), + "unexpected GCFLAG_NO_HEAP_PTRS") # ____________________________________________________________ Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gc/hybrid.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/memory/gc/hybrid.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/memory/gc/hybrid.py Tue May 6 18:30:34 2008 @@ -470,21 +470,28 @@ GenerationGC.debug_check_object(self, obj) tid = self.header(obj).tid if tid & GCFLAG_UNVISITED: - assert self.header(obj)._obj in self._d_gen2ro + ll_assert(self.gen2_rawmalloced_objects.contains(obj), + "GCFLAG_UNVISITED on non-gen2 object") def debug_check_consistency(self): if self.DEBUG: - self._make_dict("gen2_rawmalloced_objects", "_d_gen2ro") GenerationGC.debug_check_consistency(self) - def check_gen2(obj, ignored): - tid = self.header(obj).tid - assert tid & GCFLAG_EXTERNAL - assert tid & GCFLAG_UNVISITED - assert (tid & GCFLAG_AGE_MASK) < GCFLAG_AGE_MAX - def check_gen3(obj, ignored): - tid = self.header(obj).tid - assert tid & GCFLAG_EXTERNAL - assert not (tid & GCFLAG_UNVISITED) - assert (tid & GCFLAG_AGE_MASK) == GCFLAG_AGE_MAX - self.gen2_rawmalloced_objects.foreach(check_gen2, None) - self.gen3_rawmalloced_objects.foreach(check_gen3, None) + self.gen2_rawmalloced_objects.foreach(self._debug_check_gen2, None) + self.gen3_rawmalloced_objects.foreach(self._debug_check_gen3, None) + + def _debug_check_gen2(self, obj, ignored): + tid = self.header(obj).tid + ll_assert(bool(tid & GCFLAG_EXTERNAL), + "gen2: missing GCFLAG_EXTERNAL") + ll_assert(bool(tid & GCFLAG_UNVISITED), + "gen2: missing GCFLAG_UNVISITED") + ll_assert((tid & GCFLAG_AGE_MASK) < GCFLAG_AGE_MAX, + "gen2: age field too large") + def _debug_check_gen3(self, obj, ignored): + tid = self.header(obj).tid + ll_assert(bool(tid & GCFLAG_EXTERNAL), + "gen3: missing GCFLAG_EXTERNAL") + ll_assert(not (tid & GCFLAG_UNVISITED), + "gen3: unexpected GCFLAG_UNVISITED") + ll_assert((tid & GCFLAG_AGE_MASK) == GCFLAG_AGE_MAX, + "gen3: wrong age field") Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gc/semispace.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/memory/gc/semispace.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/memory/gc/semispace.py Tue May 6 18:30:34 2008 @@ -575,10 +575,16 @@ """Check the invariants about 'obj' that should be true between collections.""" tid = self.header(obj).tid - if not (tid & GCFLAG_EXTERNAL): - assert not (tid & GCFLAG_FORWARDED) - assert (self.tospace <= obj < self.free) == (not (tid&GCFLAG_EXTERNAL)) - assert not (tid & GCFLAG_FINALIZATION_ORDERING) + if tid & GCFLAG_EXTERNAL: + ll_assert(tid & GCFLAG_FORWARDED, "bug: external+!forwarded") + ll_assert(not (self.tospace <= obj < self.free), + "external flag but object inside the semispaces") + else: + ll_assert(not (tid & GCFLAG_FORWARDED), "bug: !external+forwarded") + ll_assert(self.tospace <= obj < self.free, + "!external flag but object outside the semispaces") + ll_assert(not (tid & GCFLAG_FINALIZATION_ORDERING), + "unexpected GCFLAG_FINALIZATION_ORDERING") STATISTICS_NUMBERS = 0 Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gctypelayout.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/memory/gctypelayout.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/memory/gctypelayout.py Tue May 6 18:30:34 2008 @@ -291,10 +291,10 @@ # they could be changed later to point to GC heap objects. adr = llmemory.cast_ptr_to_adr(value._as_ptr()) if TYPE._gckind == "gc": - if not gc.prebuilt_gc_objects_are_static_roots: - return - else: + if gc.prebuilt_gc_objects_are_static_roots or gc.DEBUG: appendto = self.addresses_of_static_ptrs + else: + return else: appendto = self.addresses_of_static_ptrs_in_nongc for a in gc_pointers_inside(value, adr, mutable_only=True): Modified: pypy/branch/gc-tweak/pypy/rpython/memory/support.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/memory/support.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/memory/support.py Tue May 6 18:30:34 2008 @@ -124,6 +124,20 @@ count = chunk_size foreach._annspecialcase_ = 'specialize:arg(1)' + def contains(self, addr): + """Check if 'addr' is in the list. That's just a linear scan, + so it's slow!""" + chunk = self.chunk + count = self.used_in_last_chunk + while chunk: + while count > 0: + count -= 1 + if chunk.items[count] == addr: + return True + chunk = chunk.next + count = chunk_size + return False + cache[chunk_size] = AddressStack return AddressStack From arigo at codespeak.net Tue May 6 19:30:52 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 6 May 2008 19:30:52 +0200 (CEST) Subject: [pypy-svn] r54485 - pypy/branch/gc-tweak/pypy/rpython/memory/gc Message-ID: <20080506173052.5628E16840D@codespeak.net> Author: arigo Date: Tue May 6 19:30:51 2008 New Revision: 54485 Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gc/base.py Log: Oups. Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gc/base.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/memory/gc/base.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/memory/gc/base.py Tue May 6 19:30:51 2008 @@ -173,6 +173,8 @@ obj = pending.pop() self.debug_check_object(obj) self.trace(obj, self._debug_callback2, None) + self._debug_seen.delete() + self._debug_pending.delete() def _debug_record(self, obj): seen = self._debug_seen From arigo at codespeak.net Tue May 6 19:39:45 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 6 May 2008 19:39:45 +0200 (CEST) Subject: [pypy-svn] r54486 - pypy/branch/gc-tweak/pypy/rpython/memory Message-ID: <20080506173945.2E7571683E6@codespeak.net> Author: arigo Date: Tue May 6 19:39:42 2008 New Revision: 54486 Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gcwrapper.py Log: Humpf. This makes test_gc take ages now, with the linear scan :-( Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gcwrapper.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/memory/gcwrapper.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/memory/gcwrapper.py Tue May 6 19:39:42 2008 @@ -10,7 +10,7 @@ def __init__(self, llinterp, flowgraphs, gc_class, GC_PARAMS={}): self.gc = gc_class(chunk_size = 10, **GC_PARAMS) self.gc.set_root_walker(LLInterpRootWalker(self)) - self.gc.DEBUG = True + #self.gc.DEBUG = True # slows down test_gc.py a lot self.llinterp = llinterp self.prepare_graphs(flowgraphs) self.gc.setup() From arigo at codespeak.net Tue May 6 22:33:01 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 6 May 2008 22:33:01 +0200 (CEST) Subject: [pypy-svn] r54501 - in pypy/branch/gc-tweak/pypy/rpython/memory: . gc test Message-ID: <20080506203301.0924F1683E7@codespeak.net> Author: arigo Date: Tue May 6 22:33:01 2008 New Revision: 54501 Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gc/base.py pypy/branch/gc-tweak/pypy/rpython/memory/gc/generation.py pypy/branch/gc-tweak/pypy/rpython/memory/gc/hybrid.py pypy/branch/gc-tweak/pypy/rpython/memory/gcwrapper.py pypy/branch/gc-tweak/pypy/rpython/memory/support.py pypy/branch/gc-tweak/pypy/rpython/memory/test/test_support.py Log: Mostly playing around. This is all candidate for being archived in some branch instead of getting to the trunk: a tree-based low-level AddressDict implementation. Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gc/base.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/memory/gc/base.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/memory/gc/base.py Tue May 6 22:33:01 2008 @@ -162,7 +162,8 @@ """ if self.DEBUG: from pypy.rlib.objectmodel import we_are_translated - self._debug_seen = self.AddressStack() + from pypy.rpython.memory.support import AddressDict + self._debug_seen = AddressDict() self._debug_pending = self.AddressStack() if not we_are_translated(): self.root_walker._walk_prebuilt_gc(self._debug_record) @@ -179,7 +180,7 @@ def _debug_record(self, obj): seen = self._debug_seen if not seen.contains(obj): - seen.append(obj) + seen.add(obj) self._debug_pending.append(obj) def _debug_callback(self, root): obj = root.address[0] Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gc/generation.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/memory/gc/generation.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/memory/gc/generation.py Tue May 6 22:33:01 2008 @@ -453,14 +453,14 @@ "nursery object with GCFLAG_NO_YOUNG_PTRS") self.trace(obj, self._debug_no_nursery_pointer, None) elif not self.is_in_nursery(obj): - ll_assert(self.old_objects_pointing_to_young.contains(obj), + ll_assert(self._d_oopty.contains(obj), "missing from old_objects_pointing_to_young") if tid & GCFLAG_NO_HEAP_PTRS: ll_assert(self.is_last_generation(obj), "GCFLAG_NO_HEAP_PTRS on non-3rd-generation object") self.trace(obj, self._debug_no_gen1or2_pointer, None) elif self.is_last_generation(obj): - ll_assert(self.last_generation_root_objects.contains(obj), + ll_assert(self._d_lgro.contains(obj), "missing from last_generation_root_objects") def _debug_no_nursery_pointer(self, root, ignored): @@ -473,7 +473,11 @@ def debug_check_consistency(self): if self.DEBUG: + self._d_oopty = self.old_objects_pointing_to_young.stack2dict() + self._d_lgro = self.last_generation_root_objects.stack2dict() SemiSpaceGC.debug_check_consistency(self) + self._d_oopty.delete() + self._d_lgro.delete() self.old_objects_pointing_to_young.foreach( self._debug_check_flag_1, None) self.last_generation_root_objects.foreach( Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gc/hybrid.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/memory/gc/hybrid.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/memory/gc/hybrid.py Tue May 6 22:33:01 2008 @@ -470,12 +470,14 @@ GenerationGC.debug_check_object(self, obj) tid = self.header(obj).tid if tid & GCFLAG_UNVISITED: - ll_assert(self.gen2_rawmalloced_objects.contains(obj), + ll_assert(self._d_gen2ro.contains(obj), "GCFLAG_UNVISITED on non-gen2 object") def debug_check_consistency(self): if self.DEBUG: + self._d_gen2ro = self.gen2_rawmalloced_objects.stack2dict() GenerationGC.debug_check_consistency(self) + self._d_gen2ro.delete() self.gen2_rawmalloced_objects.foreach(self._debug_check_gen2, None) self.gen3_rawmalloced_objects.foreach(self._debug_check_gen3, None) Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gcwrapper.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/memory/gcwrapper.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/memory/gcwrapper.py Tue May 6 22:33:01 2008 @@ -10,7 +10,7 @@ def __init__(self, llinterp, flowgraphs, gc_class, GC_PARAMS={}): self.gc = gc_class(chunk_size = 10, **GC_PARAMS) self.gc.set_root_walker(LLInterpRootWalker(self)) - #self.gc.DEBUG = True # slows down test_gc.py a lot + self.gc.DEBUG = True self.llinterp = llinterp self.prepare_graphs(flowgraphs) self.gc.setup() Modified: pypy/branch/gc-tweak/pypy/rpython/memory/support.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/memory/support.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/memory/support.py Tue May 6 22:33:01 2008 @@ -1,5 +1,6 @@ from pypy.rpython.lltypesystem import lltype, llmemory from pypy.rlib.objectmodel import free_non_gc_object, we_are_translated +from pypy.rlib.rarithmetic import r_uint, LONG_BIT from pypy.rlib.debug import ll_assert DEFAULT_CHUNK_SIZE = 1019 @@ -124,19 +125,10 @@ count = chunk_size foreach._annspecialcase_ = 'specialize:arg(1)' - def contains(self, addr): - """Check if 'addr' is in the list. That's just a linear scan, - so it's slow!""" - chunk = self.chunk - count = self.used_in_last_chunk - while chunk: - while count > 0: - count -= 1 - if chunk.items[count] == addr: - return True - chunk = chunk.next - count = chunk_size - return False + def stack2dict(self): + result = AddressDict() + self.foreach(result.setitem, llmemory.NULL) + return result cache[chunk_size] = AddressStack return AddressStack @@ -207,3 +199,152 @@ cache[chunk_size] = AddressDeque return AddressDeque + + +def AddressDict(): + if we_are_translated(): + return LLAddressDict() + else: + return BasicAddressDict() + +class BasicAddressDict(object): + def __init__(self): + self.data = {} + def _key(self, addr): + return addr._fixup().ptr._obj + def delete(self): + pass + def contains(self, keyaddr): + return self._key(keyaddr) in self.data + def get(self, keyaddr, default=llmemory.NULL): + return self.data.get(self._key(keyaddr), default) + def setitem(self, keyaddr, valueaddr): + assert keyaddr + self.data[self._key(keyaddr)] = valueaddr + def add(self, keyaddr): + self.setitem(keyaddr, llmemory.NULL) + +# if diff_bit == -1, the node is a key/value pair (key=left/value=right) +# if diff_bit >= 0, then the node is the root of a subtree where: +# * the keys have all exactly the same bits > diff_bit +# * the keys whose 'diff_bit' is 0 are in the 'left' subtree +# * the keys whose 'diff_bit' is 1 are in the 'right' subtree +ADDRDICTNODE = lltype.Struct('AddrDictNode', + ('diff_bit', lltype.Signed), + ('left', llmemory.Address), + ('right', llmemory.Address)) + +class LLAddressDict(object): + _alloc_flavor_ = "raw" + + def __init__(self): + self.root = lltype.malloc(ADDRDICTNODE, flavor='raw') + self.root.diff_bit = -1 + self.root.left = llmemory.NULL + + def delete(self): + node = self.root + parent = lltype.nullptr(ADDRDICTNODE) + while True: + if node.diff_bit >= 0: + next = _node_reveal(node.left) + node.left = _node_hide(parent) + parent = node + node = next + else: + lltype.free(node, flavor='raw') + if not parent: + break + node = _node_reveal(parent.right) + grandparent = _node_reveal(parent.left) + lltype.free(parent, flavor='raw') + parent = grandparent + free_non_gc_object(self) + + def contains(self, keyaddr): + if keyaddr: + node = self._lookup(keyaddr) + return keyaddr == node.left + else: + return False + + def get(self, keyaddr, default=llmemory.NULL): + if keyaddr: + node = self._lookup(keyaddr) + if keyaddr == node.left: + return node.right + return default + + def setitem(self, keyaddr, valueaddr): + ll_assert(bool(keyaddr), "cannot store NULL in an AddressDict") + node = self._lookup(keyaddr) + if node.left == llmemory.NULL or node.left == keyaddr: + node.left = keyaddr + node.right = valueaddr + else: + number1 = r_uint(llmemory.cast_adr_to_int(keyaddr)) + number2 = r_uint(llmemory.cast_adr_to_int(node.left)) + diff = number1 ^ number2 + parentnode = self._lookup(keyaddr, difflimit = diff >> 1) + # all subnodes of parentnode have a key that is equal to + # 'keyaddr' for all bits in range(0, msb(diff)), and differs + # from 'keyaddr' exactly at bit msb(diff). + # At this point, parentnode.diff_bit < msb(diff). + nextbit = parentnode.diff_bit + copynode = lltype.malloc(ADDRDICTNODE, flavor='raw') + copynode.diff_bit = nextbit + copynode.left = parentnode.left + copynode.right = parentnode.right + bit = self._msb(diff, nextbit + 1) + newnode = lltype.malloc(ADDRDICTNODE, flavor='raw') + parentnode.diff_bit = bit + ll_assert(number1 & (r_uint(1) << bit) != + number2 & (r_uint(1) << bit), "setitem: bad 'bit'") + if number1 & (r_uint(1) << bit): + parentnode.left = _node_hide(copynode) + parentnode.right = _node_hide(newnode) + else: + parentnode.left = _node_hide(newnode) + parentnode.right = _node_hide(copynode) + newnode.diff_bit = -1 + newnode.left = keyaddr + newnode.right = valueaddr + if not we_are_translated(): + assert self.contains(keyaddr) + + def add(self, keyaddr): + self.setitem(keyaddr, llmemory.NULL) + + def _msb(self, value, lowerbound=0): + # Most Significant Bit: '(1<= (r_uint(1) << lowerbound), + "msb: bad value or lowerbound") + if value >= (r_uint(1) << (LONG_BIT-1)): + return LONG_BIT-1 # most significant possible bit + bit = lowerbound + while (value >> bit) > r_uint(1): + bit += 1 + return bit + + def _lookup(self, addr, difflimit=r_uint(0)): + # * with difflimit == 0, find and return the leaf node whose key is + # equal to or closest from 'addr'. + # * with difflimit > 0, look for the node N closest to the root such + # that all the keys of the subtree starting at node N are equal to + # the given 'addr' at least for all bits > msb(difflimit). + number = r_uint(llmemory.cast_adr_to_int(addr)) + node = self.root + while node.diff_bit >= 0: + mask = r_uint(1) << node.diff_bit + if mask <= difflimit: + return node + if number & mask: + node = _node_reveal(node.right) + else: + node = _node_reveal(node.left) + return node + +_node_hide = llmemory.cast_ptr_to_adr + +def _node_reveal(nodeaddr): + return llmemory.cast_adr_to_ptr(nodeaddr, lltype.Ptr(ADDRDICTNODE)) Modified: pypy/branch/gc-tweak/pypy/rpython/memory/test/test_support.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/memory/test/test_support.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/memory/test/test_support.py Tue May 6 22:33:01 2008 @@ -1,6 +1,8 @@ +import sys from pypy.rlib.objectmodel import free_non_gc_object from pypy.rpython.memory.support import get_address_stack from pypy.rpython.memory.support import get_address_deque +from pypy.rpython.memory.support import LLAddressDict from pypy.rpython.test.test_llinterp import interpret from pypy.rpython.lltypesystem import lltype, llmemory @@ -139,3 +141,44 @@ AddressStack = get_address_stack() res = interpret(f, [], malloc_check=False) assert res + + +def test_LLAddressDict(): + import random + + class intaddr(object): + _TYPE = llmemory.Address + def __init__(self, intval): + self.intval = intval + def _cast_to_int(self): + return self.intval + def __repr__(self): + return '' % (self.intval & (sys.maxint*2+1),) + def __eq__(self, other): + return isinstance(other, intaddr) and self.intval == other.intval + def __ne__(self, other): + return not self.__eq__(other) + + for i in range(8) + range(8, 80, 10): + examples = {} + lst = [] + for j in range(i): + if j % 17 == 13: + intval = random.choice(lst) + else: + intval = random.randrange(-sys.maxint, sys.maxint) or 1 + lst.append(intval) + examples[intval] = True + + d = LLAddressDict() + for intval in lst: + d.setitem(intaddr(intval), intaddr(-intval)) + for intval in lst: + assert d.contains(intaddr(intval)) + assert d.get(intaddr(intval), "???").intval == -intval + for intval in lst: + for j in range(intval-5, intval+5): + if j not in examples: + assert not d.contains(intaddr(j)) + assert not d.contains(llmemory.NULL) + d.delete() From antocuni at codespeak.net Tue May 6 22:44:54 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 6 May 2008 22:44:54 +0200 (CEST) Subject: [pypy-svn] r54507 - pypy/extradoc/talk/roadshow-google Message-ID: <20080506204454.6A83F1683F2@codespeak.net> Author: antocuni Date: Tue May 6 22:44:53 2008 New Revision: 54507 Added: pypy/extradoc/talk/roadshow-google/flowgraph.png - copied unchanged from r53167, pypy/extradoc/talk/roadshow-ibm/flowgraph.png Log: it seems that this file was missing From antocuni at codespeak.net Wed May 7 00:03:15 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 7 May 2008 00:03:15 +0200 (CEST) Subject: [pypy-svn] r54510 - pypy/extradoc/talk/pycon-italy-2008 Message-ID: <20080506220315.0B34E168404@codespeak.net> Author: antocuni Date: Wed May 7 00:03:14 2008 New Revision: 54510 Added: pypy/extradoc/talk/pycon-italy-2008/flowgraph.png - copied unchanged from r53167, pypy/extradoc/talk/roadshow-ibm/flowgraph.png Modified: pypy/extradoc/talk/pycon-italy-2008/motivation.txt pypy/extradoc/talk/pycon-italy-2008/technical.txt Log: more tweaks Modified: pypy/extradoc/talk/pycon-italy-2008/motivation.txt ============================================================================== --- pypy/extradoc/talk/pycon-italy-2008/motivation.txt (original) +++ pypy/extradoc/talk/pycon-italy-2008/motivation.txt Wed May 7 00:03:14 2008 @@ -233,15 +233,3 @@ * By construction all interpreter/language features are supported -pypy-c-jit -====================== - -PyPy 1.0 contains both the dynamic compiler generator and the start of -its application to PyPy's Python intepreter. - -JIT refactoring in-progress. - -* included are backends for IA32 and PPC -* experimental/incomplete CLI backend -* integer arithmetic operations are optimized -* for these, we are in the speed range of ``gcc -O0`` Modified: pypy/extradoc/talk/pycon-italy-2008/technical.txt ============================================================================== --- pypy/extradoc/talk/pycon-italy-2008/technical.txt (original) +++ pypy/extradoc/talk/pycon-italy-2008/technical.txt Wed May 7 00:03:14 2008 @@ -5,20 +5,11 @@ ======================================================================== The Art of Generating Virtual Machines -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -.. raw:: html - -
-
- - - - - -
Samuele Pedroni   Laura Creighton
Armin RigoJacob Hall?n
- http://codespeak.net/pypy/ -
+:Author: Antonio Cuni (DISI - University of Genova) +:Place: PyCon Due +:Date: May 10th, 2008 Translation @@ -87,16 +78,6 @@ also uses Flow Graph transformation and rewriting. -Representation choice -======================== - -A complex part of RPython translation: - -* RPython types are still rich - -* we have to choose implementations and representations - that work for the target platforms (C vs. OO VMs) - Type Systems ========================= @@ -117,19 +98,9 @@ * turns them into *LL Flow Graphs* or *OO Flow Graphs* -* which are then sent to the backends. - -Type systems and helpers -=========================== +* the flowgraphs are transformed in various ways -We have emulation of the type systems that can run on top of CPython -for testing but also for: - -- constructing and representing the prebuilt data that our approach involves - (we start from live objects) - -- helper functions (e.g. implementations of RPython types) - use the emulations which our translation knows about too +* then they are sent to the backends. Translation aspects @@ -267,15 +238,29 @@ constant-propagate it into the Python interpreter. + +PE for dummies +============== + ++---------------------+--------------------+-----------------------+ +| | def f(x, y): | | *(case x=3)* | | *(case x=10)* | +| | x2 = x * x | | def f_3(y): | | def f_10(y): | +| | y2 = y * y | | y2 = y * y | | y2 = y * y | +| | return x2 + y2 | | return 9 + y2 | | return 100 + y2 | ++---------------------+--------------------+-----------------------+ + +* What happens if x is the bytecode instead of an integer? + + Challenges ====================== -* Effective dynamic compilation requires feedback of runtime - information into compile-time - * A shortcoming of PE is that in many cases not much can be really assumed constant at compile-time: poor results +* Effective dynamic compilation requires feedback of runtime + information into compile-time + * For a dynamic language: types are a primary example Solution: Promotion @@ -312,20 +297,19 @@ * By construction all interpreter/language features are supported + pypy-c-jit ====================== -.. where to put this? - PyPy 1.0 contains both the dynamic compiler generator and the start of its application to PyPy's Python intepreter. +JIT refactoring in-progress. + * included are backends for IA32 and PPC +* experimental/incomplete CLI backend * integer arithmetic operations are optimized * for these, we are in the speed range of ``gcc -O0`` -* demo (63x faster than CPython) - -.. demo f1 EXTRA MATERIAL @@ -333,28 +317,62 @@ * More about the JIT Generation: - - The *Timeshifting* transformation + - The *Rainbow interpreter* - *Virtuals* and *Promotion* -* More on the Stackless transformation - - *Resume points* +Execution steps +=============== + +* Translation time + + - pypy-c-jit is translated into an executable -* More on any other part that you are interested in + - the JIT compiler is automatically generated -* More demos +* Compile-time: the JIT compiler runs +* Runtime: the JIT compiled code runs -The transformation +* Compile-time and runtime are intermixed + + +The Rainbow interpreter ================================== -* The generation process is implemented as a - transformation of the low-level control flow graphs - of the interpreter +* A special interpreter whose goal is to produce executable code + +* Written in RPython * Guided by a binding time analysis ("color" of the graphs) -* *"timeshifting"* +* Green operations: executed at compile-time + +* Red operations: produce code that executes the operation at runtime + + +Rainbow architecture +==================== + +* (translation time) + +* Low-level flowgraphs are produced + +* The *hint-annotator* colors the variables + +* The *rainbow codewriter* translates flowgraphs into rainbow bytecode + +* (compile-time) + +* The rainbow interpreter executes the bytecode + +* As a result, it procude executable code + +* (runtime) + +* The code produced by the rainbow interpreter is executed + + Coloring ================= @@ -368,7 +386,7 @@ We reuse the type inference framework to propagate colors -Timeshifting Basics +PE with colors ==================== * Green operations: unchanged, executed at compile-time @@ -382,7 +400,7 @@ | | ``return`` :green:`x2` ``+`` :red:`y2` | | ``return 9 + y2`` | | ``return 100 + y2`` | +-----------------------------------------------+-----------------------------------------+----------------------------------------------+ -Timeshifting Control Flow +PE Control Flow =========================== - red split points: schedule multiple compilation states @@ -509,15 +527,3 @@ - outside world access gets intercepted to be able to force lazy virtual data into the heap - -Resume points -=============== - -Based on the Stackless Transformation: - -- this transformation can also insert code that allows to construct - artificial chains of activation states corresponding to labeled points in the - program - -- we use this to support resuming serialized language-level coroutines - From antocuni at codespeak.net Wed May 7 11:24:05 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 7 May 2008 11:24:05 +0200 (CEST) Subject: [pypy-svn] r54516 - pypy/extradoc/talk/pycon-italy-2008 Message-ID: <20080507092405.32D09168410@codespeak.net> Author: antocuni Date: Wed May 7 11:24:04 2008 New Revision: 54516 Added: pypy/extradoc/talk/pycon-italy-2008/makepdf (contents, props changed) pypy/extradoc/talk/pycon-italy-2008/stylesheet.latex Modified: pypy/extradoc/talk/pycon-italy-2008/motivation.txt pypy/extradoc/talk/pycon-italy-2008/technical.txt Log: - include technical.txt into motivation.txt - make it rst2beamer friendly Added: pypy/extradoc/talk/pycon-italy-2008/makepdf ============================================================================== --- (empty file) +++ pypy/extradoc/talk/pycon-italy-2008/makepdf Wed May 7 11:24:04 2008 @@ -0,0 +1,3 @@ +#!/bin/bash + +rst2beamer.py --stylesheet=stylesheet.latex motivation.txt motivation.latex && pdflatex motivation.latex Modified: pypy/extradoc/talk/pycon-italy-2008/motivation.txt ============================================================================== --- pypy/extradoc/talk/pycon-italy-2008/motivation.txt (original) +++ pypy/extradoc/talk/pycon-italy-2008/motivation.txt Wed May 7 11:24:04 2008 @@ -1,15 +1,14 @@ .. include:: -======================================================================== - PyPy -======================================================================== - -The Art of Generating Virtual Machines -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:Author: Antonio Cuni (DISI - University of Genova) -:Place: PyCon Due -:Date: May 10th, 2008 +.. raw:: latex + + \author[Antonio Cuni]{Antonio Cuni -- DISI, Universit? degli Studi di Genova} + \institute[PyCon Due 2008]{PyCon Due 2008 - Firenze} + \date{May 10, 2008} + + +PyPy and The Art of Generating Virtual Machines +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PyPy @@ -233,3 +232,4 @@ * By construction all interpreter/language features are supported +.. include:: technical.txt Added: pypy/extradoc/talk/pycon-italy-2008/stylesheet.latex ============================================================================== --- (empty file) +++ pypy/extradoc/talk/pycon-italy-2008/stylesheet.latex Wed May 7 11:24:04 2008 @@ -0,0 +1,7 @@ +\usetheme{Boadilla} +\setbeamercovered{transparent} +\setbeamertemplate{navigation symbols}{} + +\definecolor{darkgreen}{rgb}{0, 0.5, 0.0} +\newcommand{\docutilsrolegreen}[1]{\color{darkgreen} #1 \normalcolor} +\newcommand{\docutilsrolered}[1]{\color{red} #1 \normalcolor} Modified: pypy/extradoc/talk/pycon-italy-2008/technical.txt ============================================================================== --- pypy/extradoc/talk/pycon-italy-2008/technical.txt (original) +++ pypy/extradoc/talk/pycon-italy-2008/technical.txt Wed May 7 11:24:04 2008 @@ -1,15 +1,3 @@ -.. include:: - -======================================================================== - PyPy -======================================================================== - -The Art of Generating Virtual Machines -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -:Author: Antonio Cuni (DISI - University of Genova) -:Place: PyCon Due -:Date: May 10th, 2008 Translation From cami at codespeak.net Wed May 7 11:27:47 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Wed, 7 May 2008 11:27:47 +0200 (CEST) Subject: [pypy-svn] r54517 - pypy/branch/gameboy-emulator/pypy/lang/gameboy Message-ID: <20080507092747.0EFAA16840F@codespeak.net> Author: cami Date: Wed May 7 11:27:46 2008 New Revision: 54517 Added: pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboyImplementation.py Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboy.py Log: create gameboy pyglet test implementation if it would run, should create a new window Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py Wed May 7 11:27:46 2008 @@ -2,6 +2,7 @@ class Register(object): + def __init__(self, cpu, value=0): self.resetValue = self.value = value self.cpu = cpu @@ -31,11 +32,11 @@ def __init__(self, cpu, hi=None, lo=None, resetValue=0): self.cpu = cpu - if isinstance(hi, (Register)) : - self.hi = hi - else: + if hi == None : self.hi = Register(self.cpu) - if lo==None: + else: + self.hi = hi + if lo == None: self.lo = Register(self.cpu) else: self.lo = lo @@ -87,6 +88,7 @@ # ------------------------------------------------------------------------------ class ImmediatePseudoRegister(object): + def __init__(self, cpu, hl): self.cpu = cpu self.hl = hl @@ -182,24 +184,24 @@ self.reset() def iniRegisters(self): - self.b = Register(self) - self.c = Register(self) + self.b = Register(self) + self.c = Register(self) self.bc = DoubleRegister(self, self.b, self.c, constants.RESET_BC) - self.d = Register(self) - self.e = Register(self) + self.d = Register(self) + self.e = Register(self) self.de = DoubleRegister(self, self.d, self.e, constants.RESET_DE) - self.h = Register(self) - self.l = Register(self) + self.h = Register(self) + self.l = Register(self) self.hl = DoubleRegister(self, self.h, self.l, constants.RESET_HL) self.hli = ImmediatePseudoRegister(self, self.hl) - self.pc = DoubleRegister(self, resetValue=constants.RESET_PC) - self.sp = DoubleRegister(self, resetValue=constants.RESET_SP) + self.pc = DoubleRegister(self, resetValue=constants.RESET_PC) + self.sp = DoubleRegister(self, resetValue=constants.RESET_SP) - self.a = Register(self, constants.RESET_A) - self.f = FlagRegister(self) + self.a = Register(self, constants.RESET_A) + self.f = FlagRegister(self) self.af = DoubleRegister(self, self.a, self.f) @@ -207,9 +209,9 @@ self.resetRegisters() self.f.reset() self.f.zFlag = True - self.ime = False - self.halted = False - self.cycles = 0 + self.ime = False + self.halted = False + self.cycles = 0 def resetRegisters(self): self.a.reset() Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboy.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboy.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboy.py Wed May 7 11:27:46 2008 @@ -4,16 +4,16 @@ GameBoy Scheduler and Memory Mapper """ -from pypy.lang.gameboy import constants -from pypy.lang.gameboy.cpu import * +from pypy.lang.gameboy import constants +from pypy.lang.gameboy.cpu import * from pypy.lang.gameboy.cartridge import * from pypy.lang.gameboy.interrupt import * -from pypy.lang.gameboy.joypad import * -from pypy.lang.gameboy.ram import * -from pypy.lang.gameboy.serial import * -from pypy.lang.gameboy.sound import * -from pypy.lang.gameboy.timer import * -from pypy.lang.gameboy.video import * +from pypy.lang.gameboy.joypad import * +from pypy.lang.gameboy.ram import * +from pypy.lang.gameboy.serial import * +from pypy.lang.gameboy.sound import * +from pypy.lang.gameboy.timer import * +from pypy.lang.gameboy.video import * from pypy.lang.gameboy.cartridge import * Added: pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboyImplementation.py ============================================================================== --- (empty file) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboyImplementation.py Wed May 7 11:27:46 2008 @@ -0,0 +1,127 @@ + +import pyglet +pyglet.options['audio'] = ('openal', 'silent') + +from pyglet import window +from pyglet.window import key +from pyglet import media + +from pypy.lang.gameboy.joypad import JoypadDriver +from pypy.lang.gameboy.video import VideoDriver +from pypy.lang.gameboy.sound import SoundDriver + + +# GAMEBOY ---------------------------------------------------------------------- + +class GameBoyImplementation(GameBoy): + + def __init__(self): + self.iniWindow() + GameBoy.__init__(self) + + def iniWindow(self): + self.win = window.Window() + + def createDrivers(self): + self.clock = Clock() + self.joypadDriver = JoypadDriverImplementation(self.win) + self.videoDriver = VideoDriverImplementation(self.win) + self.soundDriver = SoundDriverImplementation(self.win) + + +# JOYPAD DRIVER ---------------------------------------------------------------- + +class JoypadDriverImplementation(object): + + def __ini__(self, win): + JoypadDriver.__ini__(self) + self.crateButtonKeyCodes() + self.win = win + self.createListeners() + + def crateButtonKeyCodes(self): + self.buttonKeyCodes = {key.UP : (self.buttonUp), + key.RIGHT : (self.buttonRight), + key.DOWN : (self.buttonDown), + key.LEFT : (self.buttonLeft), + key.ENTER : (self.buttonStart), + key.SPACE : (self.buttonSelect), + key.A : (self.buttonA), + key.B : (self.ButtonB)} + + def createListeners(self): + self.win.on_key_press = self.on_key_press + self.win.on_key_release = self.on_key_press + + def on_key_press(symbol, modifiers): + pressButtonFunction = self.getButton(symbol, modifiers) + if pressButtonFunction != None: + pressButtonFunction(True) + + def on_key_release(symbol, modifiers): + pressButtonFunction = self.getButton(symbol, modifiers) + if pressButtonFunction != None: + pressButtonFunction(False) + + def getButton(self, symbol, modifiers): + if symbol in self.buttonKeyCodes: + if len(self.buttonKeyCodes[symbol]) == 1 or\ + self.buttonKeyCodes[symbol][1] == modifiers: + return self.buttonKeyCodes[symbol][0] + return None + + +# SOUND DRIVER ----------------------------------------------------------------- + +class SoundDriverImplementation(SoundDriver): + + def __init__(self): + SoundDriver.__init__(self) + self.createSoundDriver() + self.enabled = True + self.sampleRate = 44100 + self.channelCount = 2 + self.bitsPerSample = 8 + + def createSoundDriver(self): + + def start(self): + pass + + def stop(self): + pass + + def write(self, buffer, length): + pass + + +# VIDEO DRIVER ----------------------------------------------------------------- + +class VideoDriverImplementation(VideoDriver): + + def __init__(self, win): + VideoDriver.__init__(self) + self.win = win + self.win.on_resize = self.on_resize + self.setWindowSize() + self.createImageBuffer() + + def createImageBuffer(self): + self.buffers = image.get_buffer_manager() + self.imageBuffer = self.buffers.get_color_buffer() + + def on_resize(self, width, height): + pass + + def setWindowSize(self): + self.win.setSize(self.width, self.height) + + def updateDisplay(self): + self.clearPixels() + + +# ============================================================================== + +if __name__ == '__main__': + print "starting gameboy" + gameboy = GameBoyImplementation() From antocuni at codespeak.net Wed May 7 12:26:00 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 7 May 2008 12:26:00 +0200 (CEST) Subject: [pypy-svn] r54519 - pypy/extradoc/talk/pycon-italy-2008 Message-ID: <20080507102600.961E316840C@codespeak.net> Author: antocuni Date: Wed May 7 12:26:00 2008 New Revision: 54519 Added: pypy/extradoc/talk/pycon-italy-2008/author.latex Modified: pypy/extradoc/talk/pycon-italy-2008/makepdf pypy/extradoc/talk/pycon-italy-2008/motivation.txt Log: I did't find a way to specify what goes in \author; this is a workaround Added: pypy/extradoc/talk/pycon-italy-2008/author.latex ============================================================================== --- (empty file) +++ pypy/extradoc/talk/pycon-italy-2008/author.latex Wed May 7 12:26:00 2008 @@ -0,0 +1,4 @@ +\title{PyPy and The Art of Generating Virtual Machines} +\author[Antonio Cuni]{Antonio Cuni -- DISI, Universit? degli Studi di Genova} +\institute[PyCon Due 2008]{PyCon Due 2008 - Firenze} +\date{May 10, 2008} Modified: pypy/extradoc/talk/pycon-italy-2008/makepdf ============================================================================== --- pypy/extradoc/talk/pycon-italy-2008/makepdf (original) +++ pypy/extradoc/talk/pycon-italy-2008/makepdf Wed May 7 12:26:00 2008 @@ -1,3 +1,9 @@ #!/bin/bash -rst2beamer.py --stylesheet=stylesheet.latex motivation.txt motivation.latex && pdflatex motivation.latex +# WARNING: to work, it needs this patch for docutils +# https://sourceforge.net/tracker/?func=detail&atid=422032&aid=1459707&group_id=38414 + +rst2beamer.py --stylesheet=stylesheet.latex motivation.txt motivation.latex || exit +sed 's/\\date{}/\\input{author.latex}/' -i motivation.latex || exit +pdflatex motivation.latex || exit + Modified: pypy/extradoc/talk/pycon-italy-2008/motivation.txt ============================================================================== --- pypy/extradoc/talk/pycon-italy-2008/motivation.txt (original) +++ pypy/extradoc/talk/pycon-italy-2008/motivation.txt Wed May 7 12:26:00 2008 @@ -1,12 +1,5 @@ .. include:: -.. raw:: latex - - \author[Antonio Cuni]{Antonio Cuni -- DISI, Universit? degli Studi di Genova} - \institute[PyCon Due 2008]{PyCon Due 2008 - Firenze} - \date{May 10, 2008} - - PyPy and The Art of Generating Virtual Machines ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ From antocuni at codespeak.net Wed May 7 12:45:11 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 7 May 2008 12:45:11 +0200 (CEST) Subject: [pypy-svn] r54521 - pypy/extradoc/talk/pycon-italy-2008 Message-ID: <20080507104511.B78A0168404@codespeak.net> Author: antocuni Date: Wed May 7 12:45:10 2008 New Revision: 54521 Modified: pypy/extradoc/talk/pycon-italy-2008/makepdf pypy/extradoc/talk/pycon-italy-2008/motivation.txt Log: shuffle some slides around, and some more tweaks Modified: pypy/extradoc/talk/pycon-italy-2008/makepdf ============================================================================== --- pypy/extradoc/talk/pycon-italy-2008/makepdf (original) +++ pypy/extradoc/talk/pycon-italy-2008/makepdf Wed May 7 12:45:10 2008 @@ -3,7 +3,7 @@ # WARNING: to work, it needs this patch for docutils # https://sourceforge.net/tracker/?func=detail&atid=422032&aid=1459707&group_id=38414 -rst2beamer.py --stylesheet=stylesheet.latex motivation.txt motivation.latex || exit +rst2beamer.py --stylesheet=stylesheet.latex --documentoptions=14pt motivation.txt motivation.latex || exit sed 's/\\date{}/\\input{author.latex}/' -i motivation.latex || exit pdflatex motivation.latex || exit Modified: pypy/extradoc/talk/pycon-italy-2008/motivation.txt ============================================================================== --- pypy/extradoc/talk/pycon-italy-2008/motivation.txt (original) +++ pypy/extradoc/talk/pycon-italy-2008/motivation.txt Wed May 7 12:45:10 2008 @@ -66,41 +66,6 @@ * Flexible and easy to evolve, if written in high-level language (without low-level details) -The PyPy Project -================== - -We built enough infrastructure such that: - -* speed is regained - -* features requiring low-level manipulations are (re-)added as *aspects* - -* interpreters are kept simple and uncluttered - -Targets as different as C and the industry OO VMs (JVM, CLR) are supported. - -PyPy as a project -=================== - -We operate both as an open source with production usage aspirations and -research project. - -We focus on the whole system. - -We want the tool-chain itself to be as simple as possible -(but not simpler). - -Some of what we do is relatively straight-forward, some is challenging -(generating dynamic compilers!). - -The Origin of PyPy -===================== - -PyPy is a reaction to the frustrations, resource problems and -duplicated efforts of how mainstream open-source languages (like -Python) are implemented now. - - Folk Wisdom ==================================================== @@ -141,15 +106,41 @@ (CPython - Jython - IronPython) -PyPy Approach -============================= +The PyPy Project +================== -.. raw:: html +We built enough infrastructure such that: -
+* speed is regained + +* features requiring low-level manipulations are (re-)added as *aspects* + +* interpreters are kept simple and uncluttered + +Targets as different as C and the industry OO VMs (JVM, CLR) are supported. + +PyPy as a project +=================== + +- We operate both as an open source with production usage aspirations and + research project. + +- We focus on the whole system. + +- We want the tool-chain itself to be as simple as possible + (but not simpler). + +- Some of what we do is relatively straight-forward, some is challenging + (generating dynamic compilers!). + + + +PyPy Approach +============================= .. image:: overview1.png :align: center + :scale: 45 Translation ============================================== From fijal at codespeak.net Wed May 7 13:10:37 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 7 May 2008 13:10:37 +0200 (CEST) Subject: [pypy-svn] r54523 - in pypy/branch/io-improvements/pypy/rlib: . test Message-ID: <20080507111037.BA6C8168417@codespeak.net> Author: fijal Date: Wed May 7 13:10:37 2008 New Revision: 54523 Added: pypy/branch/io-improvements/pypy/rlib/rstring.py (contents, props changed) pypy/branch/io-improvements/pypy/rlib/test/test_rstring.py (contents, props changed) Log: add string builder interface Added: pypy/branch/io-improvements/pypy/rlib/rstring.py ============================================================================== --- (empty file) +++ pypy/branch/io-improvements/pypy/rlib/rstring.py Wed May 7 13:10:37 2008 @@ -0,0 +1,19 @@ + +""" String builder interface +""" + +INIT_SIZE = 100 # XXX tweak + +class StringBuilder(object): + def __init__(self, init_size=INIT_SIZE): + self.l = [] + + def append(self, s): + self.l.append(s) + + def append_char(self, c): + self.l.append(c) + + def build(self): + return "".join(self.l) + Added: pypy/branch/io-improvements/pypy/rlib/test/test_rstring.py ============================================================================== --- (empty file) +++ pypy/branch/io-improvements/pypy/rlib/test/test_rstring.py Wed May 7 13:10:37 2008 @@ -0,0 +1,9 @@ + +from pypy.rlib.rstring import StringBuilder + +def test_string_builder(): + s = StringBuilder() + s.append("a") + s.append("abc") + s.append_char("a") + assert s.build() == "aabca" From arigo at codespeak.net Wed May 7 13:18:50 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 7 May 2008 13:18:50 +0200 (CEST) Subject: [pypy-svn] r54524 - pypy/dist/pypy/translator/goal Message-ID: <20080507111850.13CFD168417@codespeak.net> Author: arigo Date: Wed May 7 13:18:49 2008 New Revision: 54524 Modified: pypy/dist/pypy/translator/goal/gcbench.py Log: Command-line arguments can be given (a list of tree depths to run the test with). Modified: pypy/dist/pypy/translator/goal/gcbench.py ============================================================================== --- pypy/dist/pypy/translator/goal/gcbench.py (original) +++ pypy/dist/pypy/translator/goal/gcbench.py Wed May 7 13:18:49 2008 @@ -142,4 +142,9 @@ if __name__ == '__main__': - main() + import sys + if len(sys.argv) > 1: + depths = [int(s) for s in sys.argv[1:]] + main(depths) + else: + main() From arigo at codespeak.net Wed May 7 13:20:18 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 7 May 2008 13:20:18 +0200 (CEST) Subject: [pypy-svn] r54525 - pypy/dist/pypy/objspace/std Message-ID: <20080507112018.A15CE168417@codespeak.net> Author: arigo Date: Wed May 7 13:20:17 2008 New Revision: 54525 Modified: pypy/dist/pypy/objspace/std/multimethod.py Log: Also dump the non-baked perform_call expressions. Modified: pypy/dist/pypy/objspace/std/multimethod.py ============================================================================== --- pypy/dist/pypy/objspace/std/multimethod.py (original) +++ pypy/dist/pypy/objspace/std/multimethod.py Wed May 7 13:20:17 2008 @@ -607,8 +607,14 @@ checklines.append(self.body) body = '\n '.join(checklines) source = 'def %s(%s):\n %s\n' % (name, ', '.join(fnargs), body) + self.debug_dump(source) + exec compile2(source) in self.miniglobals + self._function = self.miniglobals[name] + return self._function + def debug_dump(self, source): if 0: # for debugging the generated mm sources + name = self.get_function_name() f = open('/tmp/mm-source/%s' % name, 'a') for possiblename in self.possiblenames: print >> f, '#', @@ -619,10 +625,6 @@ print >> f, source f.close() - exec compile2(source) in self.miniglobals - self._function = self.miniglobals[name] - return self._function - def register_valid_types(self, types): node = self.typetree for t1 in types[:-1]: @@ -829,6 +831,7 @@ else: assert entry.body.startswith('return ') expr = entry.body[len('return '):] + entry.debug_dump(entry.body) return self.fnargs, expr, entry.miniglobals, entry.fallback def build_funcentry(self, funcnameparts, calllist, **extranames): From arigo at codespeak.net Wed May 7 13:20:43 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 7 May 2008 13:20:43 +0200 (CEST) Subject: [pypy-svn] r54526 - pypy/dist/pypy/objspace/std Message-ID: <20080507112043.90A48168417@codespeak.net> Author: arigo Date: Wed May 7 13:20:43 2008 New Revision: 54526 Modified: pypy/dist/pypy/objspace/std/builtinshortcut.py Log: Add a few missing operations to builtinshortcut. Add a table of "known missing" operations to make sure this doesn't occur any more. Modified: pypy/dist/pypy/objspace/std/builtinshortcut.py ============================================================================== --- pypy/dist/pypy/objspace/std/builtinshortcut.py (original) +++ pypy/dist/pypy/objspace/std/builtinshortcut.py Wed May 7 13:20:43 2008 @@ -21,6 +21,7 @@ # unary 'len', 'nonzero', 'repr', 'str', 'hash', 'neg', 'invert', 'index', 'iter', 'next', 'buffer', + 'getitem', 'setitem', 'int', # in-place 'inplace_add', 'inplace_sub', 'inplace_mul', 'inplace_truediv', 'inplace_floordiv', 'inplace_div', 'inplace_mod', 'inplace_pow', @@ -28,6 +29,20 @@ 'inplace_xor', ]) +KNOWN_MISSING = ['getattr', # mostly non-builtins or optimized by CALL_METHOD + 'setattr', 'delattr', 'userdel', # mostly for non-builtins + 'get', 'set', 'delete', # uncommon (except on functions) + 'delitem', 'abs', 'hex', 'oct', # rare stuff? + 'pos', 'divmod', 'cmp', # rare stuff? + 'float', 'long', 'coerce', # rare stuff? + ] + +for _name, _, _, _specialmethods in ObjSpace.MethodTable: + if _specialmethods: + assert _name in METHODS_WITH_SHORTCUT or _name in KNOWN_MISSING, ( + "operation %r should be in METHODS_WITH_SHORTCUT or KNOWN_MISSING" + % (_name,)) + def install(space, mm): """Install a function () on the space instance which invokes From cfbolz at codespeak.net Wed May 7 13:48:15 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 7 May 2008 13:48:15 +0200 (CEST) Subject: [pypy-svn] r54527 - pypy/extradoc/talk/s3-2008 Message-ID: <20080507114815.02BE716841E@codespeak.net> Author: cfbolz Date: Wed May 7 13:48:13 2008 New Revision: 54527 Added: pypy/extradoc/talk/s3-2008/spy-talk.txt Log: (tverwaes, cfbolz): outline of the s3 talk Added: pypy/extradoc/talk/s3-2008/spy-talk.txt ============================================================================== --- (empty file) +++ pypy/extradoc/talk/s3-2008/spy-talk.txt Wed May 7 13:48:13 2008 @@ -0,0 +1,40 @@ +Outline: + +PyPy Overview: + - goals, ideas + - a toolkit for writing interpreters + - interpreters written in a high-level language + - abstracting away low-level aspects + - various target environments + - sort of model-driven approach + - translation aspects + - GC + - object model details (e.g. exact memory layout, tagged pointers) + - target environment + +Big ideas: + - abstract over low-level details + - compile-time meta-programming + - shadows + +SPy: + - Interpreter + - Object Model: typical squeak object model + specific classes (which will + be replaced by shadows) + no tagged pointers + - Shadows + - Caching of interpreter-internal information + - Abstraction (Perfect place to put smalltalk-class-specific methods) + - Primitives: explain expose_primitive + - Image Loading very quickly + +Sprint + - Squeak people don't know anything about Py(Py/thon) + - PyPy people don't know anything about Squeak + -> But it still works out + +Results: + - no gc, no jit etc. all is "for free" + - woven in by pypy + - small and understandable, clean implementation + - made smaller by compile-time metaprogramming + - quick performance (+ source size) discussion From arigo at codespeak.net Wed May 7 14:37:37 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 7 May 2008 14:37:37 +0200 (CEST) Subject: [pypy-svn] r54528 - pypy/dist/pypy/rlib Message-ID: <20080507123737.028A1168417@codespeak.net> Author: arigo Date: Wed May 7 14:37:35 2008 New Revision: 54528 Modified: pypy/dist/pypy/rlib/libffi.py Log: 64-bit support. Modified: pypy/dist/pypy/rlib/libffi.py ============================================================================== --- pypy/dist/pypy/rlib/libffi.py (original) +++ pypy/dist/pypy/rlib/libffi.py Wed May 7 14:37:35 2008 @@ -217,7 +217,7 @@ lltype.Void)) USERDATA_P.TO.become(lltype.Struct('userdata', ('callback', CALLBACK_TP), - ('addarg', rffi.INT), + ('addarg', lltype.Signed), hints={'callback':True})) From arigo at codespeak.net Wed May 7 14:48:12 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 7 May 2008 14:48:12 +0200 (CEST) Subject: [pypy-svn] r54529 - in pypy/dist/pypy/objspace/std: . test Message-ID: <20080507124812.31C5316842E@codespeak.net> Author: arigo Date: Wed May 7 14:48:10 2008 New Revision: 54529 Modified: pypy/dist/pypy/objspace/std/objspace.py pypy/dist/pypy/objspace/std/test/test_longobject.py Log: Revert r50884. Sorry fijal, I couldn't understand its purpose and it breaks allworkingmodules on 64-bit machines (as shown by a new test). Modified: pypy/dist/pypy/objspace/std/objspace.py ============================================================================== --- pypy/dist/pypy/objspace/std/objspace.py (original) +++ pypy/dist/pypy/objspace/std/objspace.py Wed May 7 14:48:10 2008 @@ -15,8 +15,7 @@ from pypy.objspace.std.multimethod import FailedToImplement from pypy.objspace.descroperation import DescrOperation from pypy.objspace.std import stdtypedef -from pypy.rlib.rarithmetic import base_int, r_int, r_uint, \ - r_longlong, r_ulonglong +from pypy.rlib.rarithmetic import base_int from pypy.rlib.objectmodel import we_are_translated from pypy.rlib.jit import hint, we_are_jitted from pypy.rlib.unroll import unrolling_iterable @@ -477,8 +476,7 @@ w_result = x.__spacebind__(self) #print 'wrapping', x, '->', w_result return w_result - if isinstance(x, r_int) or isinstance(x, r_uint) or \ - isinstance(x, r_longlong) or isinstance(x, r_ulonglong): + if isinstance(x, base_int): return W_LongObject.fromrarith_int(x) # _____ below here is where the annotator should not get _____ @@ -500,7 +498,7 @@ # The following cases are even stranger. # Really really only for tests. - if isinstance(x, long): + if type(x) is long: return W_LongObject.fromlong(x) if isinstance(x, slice): return W_SliceObject(self.wrap(x.start), Modified: pypy/dist/pypy/objspace/std/test/test_longobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/test/test_longobject.py (original) +++ pypy/dist/pypy/objspace/std/test/test_longobject.py Wed May 7 14:48:10 2008 @@ -5,9 +5,13 @@ from pypy.interpreter.error import OperationError from pypy.rlib.rarithmetic import r_uint from pypy.rlib.rbigint import rbigint +from pypy.conftest import gettestobjspace class TestW_LongObject: + def setup_class(cls): + cls.space = gettestobjspace(**{"objspace.nofaking": True}) + def test_bigint_w(self): space = self.space fromlong = lobj.W_LongObject.fromlong @@ -19,6 +23,21 @@ w_obj = space.wrap(123.456) space.raises_w(space.w_TypeError, space.bigint_w, w_obj) + def test_rint_variants(self): + from pypy.rpython.tool.rfficache import platform + space = self.space + for r in platform.numbertype_to_rclass.values(): + if r is int: + continue + print r + values = [0, -1, r.MASK>>1, -(r.MASK>>1)-1] + for x in values: + if not r.SIGNED: + x &= r.MASK + w_obj = space.wrap(r(x)) + assert space.bigint_w(w_obj).eq(rbigint.fromint(x)) + + class AppTestLong: def test_add(self): assert int(123L + 12443L) == 123 + 12443 From arigo at codespeak.net Wed May 7 15:21:57 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 7 May 2008 15:21:57 +0200 (CEST) Subject: [pypy-svn] r54531 - in pypy/dist/pypy/rlib: . test Message-ID: <20080507132157.5CFF9168430@codespeak.net> Author: arigo Date: Wed May 7 15:21:56 2008 New Revision: 54531 Modified: pypy/dist/pypy/rlib/rarithmetic.py pypy/dist/pypy/rlib/rbigint.py pypy/dist/pypy/rlib/test/test_rbigint.py Log: Fix rbigint to accept any r_xxx number type when building a bigint. Add test for this. Modified: pypy/dist/pypy/rlib/rarithmetic.py ============================================================================== --- pypy/dist/pypy/rlib/rarithmetic.py (original) +++ pypy/dist/pypy/rlib/rarithmetic.py Wed May 7 15:21:56 2008 @@ -21,6 +21,11 @@ like r_int but double word size r_ulonglong like r_uint but double word size +widen(x) + if x is of a type smaller than lltype.Signed or + lltype.Unsigned, widen it to lltype.Signed. + Useful because the translator doesn't support + arithmetic on the smaller types. These are meant to be erased by translation, r_uint in the process should mark unsigned values, ovfcheck should @@ -68,6 +73,25 @@ n -= 2*LONG_TEST return int(n) +def widen(n): + from pypy.rpython.lltypesystem import lltype + if _should_widen_type(lltype.typeOf(n)): + return int(n) + else: + return n +widen._annspecialcase_ = 'specialize:argtype(0)' + +def _should_widen_type(tp): + from pypy.rpython.lltypesystem import lltype, rffi + if tp is lltype.Bool: + return True + if tp is lltype.Signed: + return False + r_class = rffi.platform.numbertype_to_rclass[tp] + assert issubclass(r_class, base_int) + return r_class.BITS < LONG_BIT +_should_widen_type._annspecialcase_ = 'specialize:memo' + del _bits, _itest, _Ltest def ovfcheck(r): Modified: pypy/dist/pypy/rlib/rbigint.py ============================================================================== --- pypy/dist/pypy/rlib/rbigint.py (original) +++ pypy/dist/pypy/rlib/rbigint.py Wed May 7 15:21:56 2008 @@ -1,5 +1,5 @@ from pypy.rlib.rarithmetic import LONG_BIT, intmask, r_uint, r_ulonglong -from pypy.rlib.rarithmetic import ovfcheck, r_longlong +from pypy.rlib.rarithmetic import ovfcheck, r_longlong, widen import math, sys @@ -613,7 +613,7 @@ return digits digits_for_most_neg_long._annspecialcase_ = "specialize:argtype(0)" -def args_from_rarith_int(x): +def args_from_rarith_int1(x): if x > 0: return digits_from_nonneg_long(x), 1 elif x == 0: @@ -631,6 +631,10 @@ else: # the most negative integer! hacks needed... return digits_for_most_neg_long(x), -1 +args_from_rarith_int1._annspecialcase_ = "specialize:argtype(0)" + +def args_from_rarith_int(x): + return args_from_rarith_int1(widen(x)) args_from_rarith_int._annspecialcase_ = "specialize:argtype(0)" # ^^^ specialized by the precise type of 'x', which is typically a r_xxx # instance from rlib.rarithmetic Modified: pypy/dist/pypy/rlib/test/test_rbigint.py ============================================================================== --- pypy/dist/pypy/rlib/test/test_rbigint.py (original) +++ pypy/dist/pypy/rlib/test/test_rbigint.py Wed May 7 15:21:56 2008 @@ -434,15 +434,25 @@ def test_args_from_rarith_int(self): from pypy.rpython.test.test_llinterp import interpret - def fn(x): - n1 = rbigint.fromrarith_int(x) - n2 = rbigint.fromrarith_int(r_uint(x)) - return '%s %s' % (n1.str(), n2.str()) - res = interpret(fn, [0]) - assert ''.join(res.chars) == '0 0' - res = interpret(fn, [sys.maxint]) - assert ''.join(res.chars) == '%d %d' % (sys.maxint, sys.maxint) - res = interpret(fn, [-sys.maxint-1]) - assert ''.join(res.chars) == '%d %d' % (-sys.maxint-1, sys.maxint+1) - res = interpret(fn, [-17]) - assert ''.join(res.chars) == '%d %d' % (-17, 2*sys.maxint+2-17) + from pypy.rpython.tool.rfficache import platform + classlist = platform.numbertype_to_rclass.values() + fnlist = [] + for r in classlist: + if r is int: + mask = sys.maxint*2+1 + signed = True + else: + mask = r.MASK + signed = r.SIGNED + values = [0, -1, mask>>1, -(mask>>1)-1] + if not signed: + values = [x & mask for x in values] + values = [r(x) for x in values] + + def fn(i): + n = rbigint.fromrarith_int(values[i]) + return n.str() + + for i in range(len(values)): + res = interpret(fn, [i]) + assert ''.join(res.chars) == str(long(values[i])) From arigo at codespeak.net Wed May 7 15:27:37 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 7 May 2008 15:27:37 +0200 (CEST) Subject: [pypy-svn] r54532 - pypy/dist/pypy/rpython/lltypesystem Message-ID: <20080507132737.2DE3D168435@codespeak.net> Author: arigo Date: Wed May 7 15:27:36 2008 New Revision: 54532 Modified: pypy/dist/pypy/rpython/lltypesystem/opimpl.py Log: This should truncate! Fixes test_rbigint. Modified: pypy/dist/pypy/rpython/lltypesystem/opimpl.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/opimpl.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/opimpl.py Wed May 7 15:27:36 2008 @@ -289,8 +289,7 @@ def op_truncate_longlong_to_int(b): assert type(b) is r_longlong - assert -sys.maxint-1 <= b <= sys.maxint - return int(b) + return intmask(b) def op_cast_pointer(RESTYPE, obj): checkptr(obj) From arigo at codespeak.net Wed May 7 15:49:23 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 7 May 2008 15:49:23 +0200 (CEST) Subject: [pypy-svn] r54533 - pypy/dist/pypy/module/_rawffi Message-ID: <20080507134923.2CC4A168421@codespeak.net> Author: arigo Date: Wed May 7 15:49:21 2008 New Revision: 54533 Modified: pypy/dist/pypy/module/_rawffi/callback.py pypy/dist/pypy/module/_rawffi/interp_rawffi.py Log: 64-bit fixes. Modified: pypy/dist/pypy/module/_rawffi/callback.py ============================================================================== --- pypy/dist/pypy/module/_rawffi/callback.py (original) +++ pypy/dist/pypy/module/_rawffi/callback.py Wed May 7 15:49:21 2008 @@ -53,12 +53,12 @@ callback, number) self.ll_buffer = rffi.cast(rffi.VOIDP, self.ll_callback.ll_closure) if tracker.DO_TRACING: - addr = rffi.cast(rffi.INT, self.ll_callback.ll_closure) + addr = rffi.cast(lltype.Signed, self.ll_callback.ll_closure) tracker.trace_allocation(addr, self) def free(self): if tracker.DO_TRACING: - addr = rffi.cast(rffi.INT, self.ll_callback.ll_closure) + addr = rffi.cast(lltype.Signed, self.ll_callback.ll_closure) tracker.trace_free(addr) del self.global_counter.CallbackPtr_by_number[self.number] free.unwrap_spec = ['self'] Modified: pypy/dist/pypy/module/_rawffi/interp_rawffi.py ============================================================================== --- pypy/dist/pypy/module/_rawffi/interp_rawffi.py (original) +++ pypy/dist/pypy/module/_rawffi/interp_rawffi.py Wed May 7 15:49:21 2008 @@ -227,7 +227,7 @@ self.ll_buffer = lltype.malloc(rffi.VOIDP.TO, size, flavor='raw', zero=True) if tracker.DO_TRACING: - ll_buf = rffi.cast(rffi.INT, self.ll_buffer) + ll_buf = rffi.cast(lltype.Signed, self.ll_buffer) tracker.trace_allocation(ll_buf, self) def getbuffer(space, self): @@ -249,7 +249,7 @@ def _free(self): if tracker.DO_TRACING: - ll_buf = rffi.cast(rffi.INT, self.ll_buffer) + ll_buf = rffi.cast(lltype.Signed, self.ll_buffer) tracker.trace_free(ll_buf) lltype.free(self.ll_buffer, flavor='raw') self.ll_buffer = lltype.nullptr(rffi.VOIDP.TO) @@ -355,7 +355,7 @@ if tracker.DO_TRACING: # XXX this is needed, because functions tend to live forever # hence our testing is not performing that well - del tracker.alloced[rffi.cast(rffi.INT, array.ll_buffer)] + del tracker.alloced[rffi.cast(lltype.Signed, array.ll_buffer)] return space.wrap(array) byptr.unwrap_spec = ['self', ObjSpace] From arigo at codespeak.net Wed May 7 16:03:28 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 7 May 2008 16:03:28 +0200 (CEST) Subject: [pypy-svn] r54534 - pypy/dist/pypy/module/_minimal_curses Message-ID: <20080507140328.90633168410@codespeak.net> Author: arigo Date: Wed May 7 16:03:28 2008 New Revision: 54534 Modified: pypy/dist/pypy/module/_minimal_curses/fficurses.py Log: 64-bit fix. Modified: pypy/dist/pypy/module/_minimal_curses/fficurses.py ============================================================================== --- pypy/dist/pypy/module/_minimal_curses/fficurses.py (original) +++ pypy/dist/pypy/module/_minimal_curses/fficurses.py Wed May 7 16:03:28 2008 @@ -33,7 +33,7 @@ def curses_setupterm(term, fd): intp = lltype.malloc(INTP.TO, 1, flavor='raw') - err = c_setupterm(term, fd, intp) + err = rffi.cast(lltype.Signed, c_setupterm(term, fd, intp)) try: if err == ERR: if intp[0] == 0: From arigo at codespeak.net Wed May 7 17:19:56 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 7 May 2008 17:19:56 +0200 (CEST) Subject: [pypy-svn] r54535 - pypy/dist/pypy/module/_minimal_curses Message-ID: <20080507151956.A0F4B168401@codespeak.net> Author: arigo Date: Wed May 7 17:19:54 2008 New Revision: 54535 Modified: pypy/dist/pypy/module/_minimal_curses/fficurses.py Log: 64-bit fixes. Modified: pypy/dist/pypy/module/_minimal_curses/fficurses.py ============================================================================== --- pypy/dist/pypy/module/_minimal_curses/fficurses.py (original) +++ pypy/dist/pypy/module/_minimal_curses/fficurses.py Wed May 7 17:19:54 2008 @@ -28,17 +28,18 @@ INT, INT, INT, INT, INT], rffi.CCHARP, compilation_info=eci) -ERR = rffi.CConstant('ERR', INT) -OK = rffi.CConstant('OK', INT) +ERR = rffi.CConstant('ERR', lltype.Signed) +OK = rffi.CConstant('OK', lltype.Signed) def curses_setupterm(term, fd): intp = lltype.malloc(INTP.TO, 1, flavor='raw') err = rffi.cast(lltype.Signed, c_setupterm(term, fd, intp)) try: if err == ERR: - if intp[0] == 0: + errret = rffi.cast(lltype.Signed, intp[0]) + if errret == 0: msg = "setupterm: could not find terminal" - elif intp[0] == -1: + elif errret == -1: msg = "setupterm: could not find terminfo database" else: msg = "setupterm: unknown error" From arigo at codespeak.net Wed May 7 17:30:22 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 7 May 2008 17:30:22 +0200 (CEST) Subject: [pypy-svn] r54536 - pypy/dist/pypy/rpython/lltypesystem Message-ID: <20080507153022.4EF2F168434@codespeak.net> Author: arigo Date: Wed May 7 17:30:21 2008 New Revision: 54536 Modified: pypy/dist/pypy/rpython/lltypesystem/llarena.py Log: 64-bit fixes. Modified: pypy/dist/pypy/rpython/lltypesystem/llarena.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/llarena.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/llarena.py Wed May 7 17:30:21 2008 @@ -391,7 +391,7 @@ sandboxsafe=True) llimpl_round_up_for_allocation = rffi.llexternal('ROUND_UP_FOR_ALLOCATION', - [rffi.INT], rffi.INT, + [lltype.Signed], lltype.Signed, sandboxsafe=True, _nowrapper=True) register_external(round_up_for_allocation, [int], int, From pypy-svn at codespeak.net Wed May 7 18:44:26 2008 From: pypy-svn at codespeak.net (VIAGRA INC) Date: Wed, 7 May 2008 18:44:26 +0200 (CEST) Subject: [pypy-svn] SALE 89% OFF Message-ID: <20010424090948.2557.qmail@bzq-79-176-237-253.red.bezeqint.net> An HTML attachment was scrubbed... URL: From arigo at codespeak.net Wed May 7 18:46:08 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 7 May 2008 18:46:08 +0200 (CEST) Subject: [pypy-svn] r54537 - pypy/dist/pypy/translator/c/src Message-ID: <20080507164608.6F3FC168453@codespeak.net> Author: arigo Date: Wed May 7 18:46:06 2008 New Revision: 54537 Modified: pypy/dist/pypy/translator/c/src/int.h Log: 64-bit fixes. Modified: pypy/dist/pypy/translator/c/src/int.h ============================================================================== --- pypy/dist/pypy/translator/c/src/int.h (original) +++ pypy/dist/pypy/translator/c/src/int.h Wed May 7 18:46:06 2008 @@ -72,7 +72,13 @@ #define OP_INT_MUL(x,y,r) r = (x) * (y) -#ifndef HAVE_LONG_LONG +#if defined(HAVE_LONG_LONG) && SIZE_OF_LONG_LONG < SIZE_OF_LONG +# define OP_INT_MUL_OVF_LL 1 +#lse +# define OP_INT_MUL_OVF_LL 0 +#endif + +#if !OP_INT_MUL_OVF_LL #define OP_INT_MUL_OVF(x,y,r) \ if (op_int_mul_ovf(x,y,&r)); \ @@ -230,7 +236,7 @@ /* _________________ certain implementations __________________ */ -#ifndef HAVE_LONG_LONG +#if !OP_INT_MUL_OVF_LL /* adjusted from intobject.c, Python 2.3.3 */ /* prototypes */ @@ -276,7 +282,7 @@ #endif /* PYPY_NOT_MAIN_FILE */ -#endif /* HAVE_LONG_LONG */ +#endif /* !OP_INT_MUL_OVF_LL */ /* implementations */ From arigo at codespeak.net Wed May 7 18:54:12 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 7 May 2008 18:54:12 +0200 (CEST) Subject: [pypy-svn] r54538 - in pypy/branch/gc-tweak/pypy: module/_minimal_curses module/_rawffi objspace/std objspace/std/test rlib rlib/test rpython/lltypesystem rpython/memory/gc translator/c/src Message-ID: <20080507165412.846E3168453@codespeak.net> Author: arigo Date: Wed May 7 18:54:11 2008 New Revision: 54538 Modified: pypy/branch/gc-tweak/pypy/module/_minimal_curses/fficurses.py pypy/branch/gc-tweak/pypy/module/_rawffi/callback.py pypy/branch/gc-tweak/pypy/module/_rawffi/interp_rawffi.py pypy/branch/gc-tweak/pypy/objspace/std/objspace.py pypy/branch/gc-tweak/pypy/objspace/std/test/test_longobject.py pypy/branch/gc-tweak/pypy/rlib/libffi.py pypy/branch/gc-tweak/pypy/rlib/rarithmetic.py pypy/branch/gc-tweak/pypy/rlib/rbigint.py pypy/branch/gc-tweak/pypy/rlib/test/test_rbigint.py pypy/branch/gc-tweak/pypy/rpython/lltypesystem/llarena.py pypy/branch/gc-tweak/pypy/rpython/lltypesystem/opimpl.py pypy/branch/gc-tweak/pypy/rpython/memory/gc/base.py pypy/branch/gc-tweak/pypy/rpython/memory/gc/generation.py pypy/branch/gc-tweak/pypy/translator/c/src/int.h Log: 64-bit fixes from the trunk: svn merge -r54527:54537 svn+ssh://codespeak.net/svn/pypy/dist Modified: pypy/branch/gc-tweak/pypy/module/_minimal_curses/fficurses.py ============================================================================== --- pypy/branch/gc-tweak/pypy/module/_minimal_curses/fficurses.py (original) +++ pypy/branch/gc-tweak/pypy/module/_minimal_curses/fficurses.py Wed May 7 18:54:11 2008 @@ -28,17 +28,18 @@ INT, INT, INT, INT, INT], rffi.CCHARP, compilation_info=eci) -ERR = rffi.CConstant('ERR', INT) -OK = rffi.CConstant('OK', INT) +ERR = rffi.CConstant('ERR', lltype.Signed) +OK = rffi.CConstant('OK', lltype.Signed) def curses_setupterm(term, fd): intp = lltype.malloc(INTP.TO, 1, flavor='raw') - err = c_setupterm(term, fd, intp) + err = rffi.cast(lltype.Signed, c_setupterm(term, fd, intp)) try: if err == ERR: - if intp[0] == 0: + errret = rffi.cast(lltype.Signed, intp[0]) + if errret == 0: msg = "setupterm: could not find terminal" - elif intp[0] == -1: + elif errret == -1: msg = "setupterm: could not find terminfo database" else: msg = "setupterm: unknown error" Modified: pypy/branch/gc-tweak/pypy/module/_rawffi/callback.py ============================================================================== --- pypy/branch/gc-tweak/pypy/module/_rawffi/callback.py (original) +++ pypy/branch/gc-tweak/pypy/module/_rawffi/callback.py Wed May 7 18:54:11 2008 @@ -53,12 +53,12 @@ callback, number) self.ll_buffer = rffi.cast(rffi.VOIDP, self.ll_callback.ll_closure) if tracker.DO_TRACING: - addr = rffi.cast(rffi.INT, self.ll_callback.ll_closure) + addr = rffi.cast(lltype.Signed, self.ll_callback.ll_closure) tracker.trace_allocation(addr, self) def free(self): if tracker.DO_TRACING: - addr = rffi.cast(rffi.INT, self.ll_callback.ll_closure) + addr = rffi.cast(lltype.Signed, self.ll_callback.ll_closure) tracker.trace_free(addr) del self.global_counter.CallbackPtr_by_number[self.number] free.unwrap_spec = ['self'] Modified: pypy/branch/gc-tweak/pypy/module/_rawffi/interp_rawffi.py ============================================================================== --- pypy/branch/gc-tweak/pypy/module/_rawffi/interp_rawffi.py (original) +++ pypy/branch/gc-tweak/pypy/module/_rawffi/interp_rawffi.py Wed May 7 18:54:11 2008 @@ -227,7 +227,7 @@ self.ll_buffer = lltype.malloc(rffi.VOIDP.TO, size, flavor='raw', zero=True) if tracker.DO_TRACING: - ll_buf = rffi.cast(rffi.INT, self.ll_buffer) + ll_buf = rffi.cast(lltype.Signed, self.ll_buffer) tracker.trace_allocation(ll_buf, self) def getbuffer(space, self): @@ -249,7 +249,7 @@ def _free(self): if tracker.DO_TRACING: - ll_buf = rffi.cast(rffi.INT, self.ll_buffer) + ll_buf = rffi.cast(lltype.Signed, self.ll_buffer) tracker.trace_free(ll_buf) lltype.free(self.ll_buffer, flavor='raw') self.ll_buffer = lltype.nullptr(rffi.VOIDP.TO) @@ -355,7 +355,7 @@ if tracker.DO_TRACING: # XXX this is needed, because functions tend to live forever # hence our testing is not performing that well - del tracker.alloced[rffi.cast(rffi.INT, array.ll_buffer)] + del tracker.alloced[rffi.cast(lltype.Signed, array.ll_buffer)] return space.wrap(array) byptr.unwrap_spec = ['self', ObjSpace] Modified: pypy/branch/gc-tweak/pypy/objspace/std/objspace.py ============================================================================== --- pypy/branch/gc-tweak/pypy/objspace/std/objspace.py (original) +++ pypy/branch/gc-tweak/pypy/objspace/std/objspace.py Wed May 7 18:54:11 2008 @@ -15,8 +15,7 @@ from pypy.objspace.std.multimethod import FailedToImplement from pypy.objspace.descroperation import DescrOperation from pypy.objspace.std import stdtypedef -from pypy.rlib.rarithmetic import base_int, r_int, r_uint, \ - r_longlong, r_ulonglong +from pypy.rlib.rarithmetic import base_int from pypy.rlib.objectmodel import we_are_translated from pypy.rlib.jit import hint, we_are_jitted from pypy.rlib.unroll import unrolling_iterable @@ -477,8 +476,7 @@ w_result = x.__spacebind__(self) #print 'wrapping', x, '->', w_result return w_result - if isinstance(x, r_int) or isinstance(x, r_uint) or \ - isinstance(x, r_longlong) or isinstance(x, r_ulonglong): + if isinstance(x, base_int): return W_LongObject.fromrarith_int(x) # _____ below here is where the annotator should not get _____ @@ -500,7 +498,7 @@ # The following cases are even stranger. # Really really only for tests. - if isinstance(x, long): + if type(x) is long: return W_LongObject.fromlong(x) if isinstance(x, slice): return W_SliceObject(self.wrap(x.start), Modified: pypy/branch/gc-tweak/pypy/objspace/std/test/test_longobject.py ============================================================================== --- pypy/branch/gc-tweak/pypy/objspace/std/test/test_longobject.py (original) +++ pypy/branch/gc-tweak/pypy/objspace/std/test/test_longobject.py Wed May 7 18:54:11 2008 @@ -5,9 +5,13 @@ from pypy.interpreter.error import OperationError from pypy.rlib.rarithmetic import r_uint from pypy.rlib.rbigint import rbigint +from pypy.conftest import gettestobjspace class TestW_LongObject: + def setup_class(cls): + cls.space = gettestobjspace(**{"objspace.nofaking": True}) + def test_bigint_w(self): space = self.space fromlong = lobj.W_LongObject.fromlong @@ -19,6 +23,21 @@ w_obj = space.wrap(123.456) space.raises_w(space.w_TypeError, space.bigint_w, w_obj) + def test_rint_variants(self): + from pypy.rpython.tool.rfficache import platform + space = self.space + for r in platform.numbertype_to_rclass.values(): + if r is int: + continue + print r + values = [0, -1, r.MASK>>1, -(r.MASK>>1)-1] + for x in values: + if not r.SIGNED: + x &= r.MASK + w_obj = space.wrap(r(x)) + assert space.bigint_w(w_obj).eq(rbigint.fromint(x)) + + class AppTestLong: def test_add(self): assert int(123L + 12443L) == 123 + 12443 Modified: pypy/branch/gc-tweak/pypy/rlib/libffi.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rlib/libffi.py (original) +++ pypy/branch/gc-tweak/pypy/rlib/libffi.py Wed May 7 18:54:11 2008 @@ -217,7 +217,7 @@ lltype.Void)) USERDATA_P.TO.become(lltype.Struct('userdata', ('callback', CALLBACK_TP), - ('addarg', rffi.INT), + ('addarg', lltype.Signed), hints={'callback':True})) Modified: pypy/branch/gc-tweak/pypy/rlib/rarithmetic.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rlib/rarithmetic.py (original) +++ pypy/branch/gc-tweak/pypy/rlib/rarithmetic.py Wed May 7 18:54:11 2008 @@ -21,6 +21,11 @@ like r_int but double word size r_ulonglong like r_uint but double word size +widen(x) + if x is of a type smaller than lltype.Signed or + lltype.Unsigned, widen it to lltype.Signed. + Useful because the translator doesn't support + arithmetic on the smaller types. These are meant to be erased by translation, r_uint in the process should mark unsigned values, ovfcheck should @@ -68,6 +73,25 @@ n -= 2*LONG_TEST return int(n) +def widen(n): + from pypy.rpython.lltypesystem import lltype + if _should_widen_type(lltype.typeOf(n)): + return int(n) + else: + return n +widen._annspecialcase_ = 'specialize:argtype(0)' + +def _should_widen_type(tp): + from pypy.rpython.lltypesystem import lltype, rffi + if tp is lltype.Bool: + return True + if tp is lltype.Signed: + return False + r_class = rffi.platform.numbertype_to_rclass[tp] + assert issubclass(r_class, base_int) + return r_class.BITS < LONG_BIT +_should_widen_type._annspecialcase_ = 'specialize:memo' + del _bits, _itest, _Ltest def ovfcheck(r): Modified: pypy/branch/gc-tweak/pypy/rlib/rbigint.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rlib/rbigint.py (original) +++ pypy/branch/gc-tweak/pypy/rlib/rbigint.py Wed May 7 18:54:11 2008 @@ -1,5 +1,5 @@ from pypy.rlib.rarithmetic import LONG_BIT, intmask, r_uint, r_ulonglong -from pypy.rlib.rarithmetic import ovfcheck, r_longlong +from pypy.rlib.rarithmetic import ovfcheck, r_longlong, widen import math, sys @@ -613,7 +613,7 @@ return digits digits_for_most_neg_long._annspecialcase_ = "specialize:argtype(0)" -def args_from_rarith_int(x): +def args_from_rarith_int1(x): if x > 0: return digits_from_nonneg_long(x), 1 elif x == 0: @@ -631,6 +631,10 @@ else: # the most negative integer! hacks needed... return digits_for_most_neg_long(x), -1 +args_from_rarith_int1._annspecialcase_ = "specialize:argtype(0)" + +def args_from_rarith_int(x): + return args_from_rarith_int1(widen(x)) args_from_rarith_int._annspecialcase_ = "specialize:argtype(0)" # ^^^ specialized by the precise type of 'x', which is typically a r_xxx # instance from rlib.rarithmetic Modified: pypy/branch/gc-tweak/pypy/rlib/test/test_rbigint.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rlib/test/test_rbigint.py (original) +++ pypy/branch/gc-tweak/pypy/rlib/test/test_rbigint.py Wed May 7 18:54:11 2008 @@ -434,15 +434,25 @@ def test_args_from_rarith_int(self): from pypy.rpython.test.test_llinterp import interpret - def fn(x): - n1 = rbigint.fromrarith_int(x) - n2 = rbigint.fromrarith_int(r_uint(x)) - return '%s %s' % (n1.str(), n2.str()) - res = interpret(fn, [0]) - assert ''.join(res.chars) == '0 0' - res = interpret(fn, [sys.maxint]) - assert ''.join(res.chars) == '%d %d' % (sys.maxint, sys.maxint) - res = interpret(fn, [-sys.maxint-1]) - assert ''.join(res.chars) == '%d %d' % (-sys.maxint-1, sys.maxint+1) - res = interpret(fn, [-17]) - assert ''.join(res.chars) == '%d %d' % (-17, 2*sys.maxint+2-17) + from pypy.rpython.tool.rfficache import platform + classlist = platform.numbertype_to_rclass.values() + fnlist = [] + for r in classlist: + if r is int: + mask = sys.maxint*2+1 + signed = True + else: + mask = r.MASK + signed = r.SIGNED + values = [0, -1, mask>>1, -(mask>>1)-1] + if not signed: + values = [x & mask for x in values] + values = [r(x) for x in values] + + def fn(i): + n = rbigint.fromrarith_int(values[i]) + return n.str() + + for i in range(len(values)): + res = interpret(fn, [i]) + assert ''.join(res.chars) == str(long(values[i])) Modified: pypy/branch/gc-tweak/pypy/rpython/lltypesystem/llarena.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/lltypesystem/llarena.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/lltypesystem/llarena.py Wed May 7 18:54:11 2008 @@ -391,7 +391,7 @@ sandboxsafe=True) llimpl_round_up_for_allocation = rffi.llexternal('ROUND_UP_FOR_ALLOCATION', - [rffi.INT], rffi.INT, + [lltype.Signed], lltype.Signed, sandboxsafe=True, _nowrapper=True) register_external(round_up_for_allocation, [int], int, Modified: pypy/branch/gc-tweak/pypy/rpython/lltypesystem/opimpl.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/lltypesystem/opimpl.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/lltypesystem/opimpl.py Wed May 7 18:54:11 2008 @@ -289,8 +289,7 @@ def op_truncate_longlong_to_int(b): assert type(b) is r_longlong - assert -sys.maxint-1 <= b <= sys.maxint - return int(b) + return intmask(b) def op_cast_pointer(RESTYPE, obj): checkptr(obj) Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gc/base.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/memory/gc/base.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/memory/gc/base.py Wed May 7 18:54:11 2008 @@ -12,7 +12,7 @@ # collection. It is automatically set to True by test_gc.py. The # checking logic is translatable, so the flag can be set to True # here before translation. - DEBUG = False + DEBUG = True def set_query_functions(self, is_varsize, has_gcptr_in_varsize, is_gcarrayofgcptr, Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gc/generation.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/memory/gc/generation.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/memory/gc/generation.py Wed May 7 18:54:11 2008 @@ -337,7 +337,7 @@ llarena.arena_reset(self.nursery, self.nursery_size, True) if DEBUG_PRINT: llop.debug_print(lltype.Void, "percent survived:", float(scan - beginning) / self.nursery_size) - self.debug_check_consistency() + #self.debug_check_consistency() else: # no nursery - this occurs after a full collect, triggered either # just above or by some previous non-nursery-based allocation. Modified: pypy/branch/gc-tweak/pypy/translator/c/src/int.h ============================================================================== --- pypy/branch/gc-tweak/pypy/translator/c/src/int.h (original) +++ pypy/branch/gc-tweak/pypy/translator/c/src/int.h Wed May 7 18:54:11 2008 @@ -72,7 +72,13 @@ #define OP_INT_MUL(x,y,r) r = (x) * (y) -#ifndef HAVE_LONG_LONG +#if defined(HAVE_LONG_LONG) && SIZE_OF_LONG_LONG < SIZE_OF_LONG +# define OP_INT_MUL_OVF_LL 1 +#lse +# define OP_INT_MUL_OVF_LL 0 +#endif + +#if !OP_INT_MUL_OVF_LL #define OP_INT_MUL_OVF(x,y,r) \ if (op_int_mul_ovf(x,y,&r)); \ @@ -230,7 +236,7 @@ /* _________________ certain implementations __________________ */ -#ifndef HAVE_LONG_LONG +#if !OP_INT_MUL_OVF_LL /* adjusted from intobject.c, Python 2.3.3 */ /* prototypes */ @@ -276,7 +282,7 @@ #endif /* PYPY_NOT_MAIN_FILE */ -#endif /* HAVE_LONG_LONG */ +#endif /* !OP_INT_MUL_OVF_LL */ /* implementations */ From arigo at codespeak.net Wed May 7 18:56:50 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 7 May 2008 18:56:50 +0200 (CEST) Subject: [pypy-svn] r54539 - pypy/branch/gc-tweak/pypy/rpython/memory/gc Message-ID: <20080507165650.9F0AB16843A@codespeak.net> Author: arigo Date: Wed May 7 18:56:50 2008 New Revision: 54539 Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gc/base.py pypy/branch/gc-tweak/pypy/rpython/memory/gc/generation.py Log: Revert accidentally checked in. Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gc/base.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/memory/gc/base.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/memory/gc/base.py Wed May 7 18:56:50 2008 @@ -12,7 +12,7 @@ # collection. It is automatically set to True by test_gc.py. The # checking logic is translatable, so the flag can be set to True # here before translation. - DEBUG = True + DEBUG = False def set_query_functions(self, is_varsize, has_gcptr_in_varsize, is_gcarrayofgcptr, Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gc/generation.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/memory/gc/generation.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/memory/gc/generation.py Wed May 7 18:56:50 2008 @@ -337,7 +337,7 @@ llarena.arena_reset(self.nursery, self.nursery_size, True) if DEBUG_PRINT: llop.debug_print(lltype.Void, "percent survived:", float(scan - beginning) / self.nursery_size) - #self.debug_check_consistency() + self.debug_check_consistency() else: # no nursery - this occurs after a full collect, triggered either # just above or by some previous non-nursery-based allocation. From antocuni at codespeak.net Wed May 7 21:00:10 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 7 May 2008 21:00:10 +0200 (CEST) Subject: [pypy-svn] r54541 - pypy/extradoc/talk/pycon-italy-2008 Message-ID: <20080507190010.16ED1168460@codespeak.net> Author: antocuni Date: Wed May 7 21:00:08 2008 New Revision: 54541 Modified: pypy/extradoc/talk/pycon-italy-2008/motivation.txt pypy/extradoc/talk/pycon-italy-2008/technical.txt Log: remove duplicate slides; some renaming Modified: pypy/extradoc/talk/pycon-italy-2008/motivation.txt ============================================================================== --- pypy/extradoc/talk/pycon-italy-2008/motivation.txt (original) +++ pypy/extradoc/talk/pycon-italy-2008/motivation.txt Wed May 7 21:00:08 2008 @@ -13,6 +13,8 @@ - a framework for writing dynamic languages +Today we will focus on the latter. + Agenda ====== @@ -119,6 +121,9 @@ Targets as different as C and the industry OO VMs (JVM, CLR) are supported. +A special aspect: **Generating JIT compilers** + + PyPy as a project =================== @@ -142,15 +147,9 @@ :align: center :scale: 45 -Translation -============================================== - -.. raw:: html - -
Going from interpreters to VMs ------------------------------- +============================== In PyPy interpreters are written in RPython: @@ -162,58 +161,7 @@ RPython is still close to Python. -A special aspect -================================== - -.. raw:: html - -
-
-
- -**Generating JIT compilers** - -.. raw:: html - -
- -JIT motivation -================================== - -Flexibility vs. Performance: - -* Interpreters are easy to write and evolve - -* For high performance, dynamic compilation is required - -Traditional JIT compilers -=============================== - -* Huge resource investment -* The richer the semantics, the harder to write -* Poor encoding of language semantics -* Hard to evolve - -Need for novel approaches! - -PyPy Approach: Goal -============================= - -.. raw:: html - -
- -.. image:: overview2.png - :align: center - -Language-agnostic -==================== - -* The dynamic generation process and primitives are language-agnostic. -* The language implementations should be able to evolve up to - maintaining the hints. -* By construction all interpreter/language features are supported .. include:: technical.txt Modified: pypy/extradoc/talk/pycon-italy-2008/technical.txt ============================================================================== --- pypy/extradoc/talk/pycon-italy-2008/technical.txt (original) +++ pypy/extradoc/talk/pycon-italy-2008/technical.txt Wed May 7 21:00:08 2008 @@ -1,40 +1,5 @@ -Translation -============================================== - -.. raw:: html - -
- -Going from interpreters to VMs ------------------------------- - -In PyPy interpreters are written in RPython: - -* A subset of Python amenable to static analysis - -* Still fully garbage collected - -* Rich built-in types - -RPython is still close to Python. - -Translation -============================================== - -.. raw:: html - -
- -Going from interpreters to VMs (2) ----------------------------------- - -The translation tool-chain implements good static compilation -of RPython to multiple targets. - -It has pluggable backends, and inserts low-level details -as needed (*translation aspects*). Translation details ======================= @@ -142,31 +107,6 @@ .. MMTk reference -Stackless transformation -========================= - -Inserts support code around calls such that the stack can be unwound. - -- Functions can store their current activation frame state to the heap - -- Chains of saved activation state can be resumed - -We have implemented coroutine switching using this. - -A special aspect -================================== - -.. raw:: html - -
-
-
- -**Generating JIT compilers** - -.. raw:: html - -
JIT motivation ================================== @@ -187,15 +127,12 @@ Need for novel approaches! -PyPy Approach: Goal +PyPy Architecture ============================= -.. raw:: html - -
- .. image:: overview2.png :align: center + :scale: 60 Basics From antocuni at codespeak.net Thu May 8 00:23:36 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 8 May 2008 00:23:36 +0200 (CEST) Subject: [pypy-svn] r54543 - pypy/extradoc/talk/pycon-italy-2008 Message-ID: <20080507222336.A04A7168477@codespeak.net> Author: antocuni Date: Thu May 8 00:23:35 2008 New Revision: 54543 Modified: pypy/extradoc/talk/pycon-italy-2008/author.latex pypy/extradoc/talk/pycon-italy-2008/motivation.txt pypy/extradoc/talk/pycon-italy-2008/stylesheet.latex pypy/extradoc/talk/pycon-italy-2008/technical.txt Log: use beamer boxes for code examples Modified: pypy/extradoc/talk/pycon-italy-2008/author.latex ============================================================================== --- pypy/extradoc/talk/pycon-italy-2008/author.latex (original) +++ pypy/extradoc/talk/pycon-italy-2008/author.latex Thu May 8 00:23:35 2008 @@ -1,4 +1,6 @@ +\definecolor{rrblitbackground}{rgb}{0.0, 0.0, 0.0} + \title{PyPy and The Art of Generating Virtual Machines} -\author[Antonio Cuni]{Antonio Cuni -- DISI, Universit? degli Studi di Genova} +\author[Antonio Cuni]{Antonio Cuni\\DISI, Universit? degli Studi di Genova} \institute[PyCon Due 2008]{PyCon Due 2008 - Firenze} \date{May 10, 2008} Modified: pypy/extradoc/talk/pycon-italy-2008/motivation.txt ============================================================================== --- pypy/extradoc/talk/pycon-italy-2008/motivation.txt (original) +++ pypy/extradoc/talk/pycon-italy-2008/motivation.txt Thu May 8 00:23:35 2008 @@ -1,4 +1,4 @@ -.. include:: +.. include:: beamerdefs.txt PyPy and The Art of Generating Virtual Machines ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Modified: pypy/extradoc/talk/pycon-italy-2008/stylesheet.latex ============================================================================== --- pypy/extradoc/talk/pycon-italy-2008/stylesheet.latex (original) +++ pypy/extradoc/talk/pycon-italy-2008/stylesheet.latex Thu May 8 00:23:35 2008 @@ -3,5 +3,8 @@ \setbeamertemplate{navigation symbols}{} \definecolor{darkgreen}{rgb}{0, 0.5, 0.0} -\newcommand{\docutilsrolegreen}[1]{\color{darkgreen} #1 \normalcolor} -\newcommand{\docutilsrolered}[1]{\color{red} #1 \normalcolor} +\newcommand{\docutilsrolegreen}[1]{\color{darkgreen}#1\normalcolor} +\newcommand{\docutilsrolered}[1]{\color{red}#1\normalcolor} + +\newcommand{\green}[1]{\color{darkgreen}#1\normalcolor} +\newcommand{\red}[1]{\color{red}#1\normalcolor} Modified: pypy/extradoc/talk/pycon-italy-2008/technical.txt ============================================================================== --- pypy/extradoc/talk/pycon-italy-2008/technical.txt (original) +++ pypy/extradoc/talk/pycon-italy-2008/technical.txt Thu May 8 00:23:35 2008 @@ -1,7 +1,7 @@ -Translation details +Translation details (1) ======================= .. raw:: html @@ -31,7 +31,7 @@ also uses Flow Graph transformation and rewriting. -Type Systems +Type Systems (1) ========================= We model the different targets through different type systems: @@ -42,7 +42,7 @@ - OO (object oriented targets): classes and instances with inheritance and dispatching -Type systems (2) +Type Systems (2) =========================== Translation: @@ -56,7 +56,7 @@ * then they are sent to the backends. -Translation aspects +Translation aspects (1) ======================== The interpreters in RPython are free of low-level details @@ -167,14 +167,38 @@ PE for dummies ============== -+---------------------+--------------------+-----------------------+ -| | def f(x, y): | | *(case x=3)* | | *(case x=10)* | -| | x2 = x * x | | def f_3(y): | | def f_10(y): | -| | y2 = y * y | | y2 = y * y | | y2 = y * y | -| | return x2 + y2 | | return 9 + y2 | | return 100 + y2 | -+---------------------+--------------------+-----------------------+ +|example<| Example |>| +:: -* What happens if x is the bytecode instead of an integer? + def f(x, y): + x2 = x * x + y2 = y * y + return x2 + y2 + +|end_example| + +|pause| +|column1| +|alert<| case x=3 |>| +:: + + def f_3(y): + y2 = y * y + return 9 + y2 + +|end_alert| + +|pause| +|column2| +|alert<| case x=10 |>| +:: + + def f_10(y): + y2 = y * y + return 100 + y2 + +|end_alert| +|end_columns| Challenges @@ -279,7 +303,7 @@ Rainbow architecture ==================== -* (translation time) +|alert<| Translation time |>| * Low-level flowgraphs are produced @@ -287,23 +311,30 @@ * The *rainbow codewriter* translates flowgraphs into rainbow bytecode -* (compile-time) +|end_alert| + +|pause| +|example<| Compile-time |>| * The rainbow interpreter executes the bytecode * As a result, it procude executable code -* (runtime) +|end_example| -* The code produced by the rainbow interpreter is executed +|pause| +|alert<| Runtime |>| +* The produced code is executed + +|end_alert| Coloring ================= -* Green: compile-time value -* Red: runtime value +* :green:`Green`: compile-time value +* :red:`Red`: runtime value * The hints give constraints from which the colors of all values are derived @@ -311,32 +342,79 @@ We reuse the type inference framework to propagate colors -PE with colors -==================== +Partial Evaluation with Colors +============================== -* Green operations: unchanged, executed at compile-time +* :green:`Green operations`: unchanged, executed at compile-time -* Red operations: converted into corresponding code emitting code +* :red:`Red operations`: converted into corresponding code emitting code -+-----------------------------------------------+-----------------------------------------+----------------------------------------------+ -| | ``def f(`` :green:`x`, :red:`y` ``):`` | | *(case x=3)* | | *(case x=10)* | -| | :green:`x2` = :green:`x` ``*`` :green:`x` | | ``def f_3(y):`` | | ``def f_10(y):`` | -| | :red:`y2` = :red:`y` ``*`` :red:`y` | | ``y2 = y * y`` | | ``y2 = y * y`` | -| | ``return`` :green:`x2` ``+`` :red:`y2` | | ``return 9 + y2`` | | ``return 100 + y2`` | -+-----------------------------------------------+-----------------------------------------+----------------------------------------------+ +|pause| +|column1| +|example<| Example |>| -PE Control Flow -=========================== +.. raw:: latex + + \smallskip + \begin{rtbliteral} + def~f(\green{x},~\red{y}):~\\ + ~~\green{x2}~=~\green{x}~*~\green{x}~\\ + ~~\red{y2}~=~\red{y}~*~\red{y}~\\ + ~~return~\green{x2}~+~\red{y2} + \end{rtbliteral} + \smallskip + +|end_example| + +|pause| +|column2| +|alert<| case x=10 |>| +:: + + def f_10(y): + y2 = y * y + return 100 + y2 + +|end_alert| +|end_columns| + + +Partial Evaluate Control Flow +=============================== - red split points: schedule multiple compilation states - merge points: merge logic to reuse code for equivalent states -+-----------------------------+----------------------------+ -| | ``if`` :red:`x`: | | :green:`(case y != 0)` | -| | ``print "x is true"`` | | ``if x:`` | -| | ``if`` :green:`y`: | | ``print "x is true"`` | -| | ``print "y is true"`` | | ``print "y is true"`` | -+-----------------------------+----------------------------+ +|pause| +|column1| +|example<| Example |>| + +.. raw:: latex + + \smallskip + \begin{rtbliteral} + if~\red{x}:\\ + ~~print~"x is true"\\ + if~\green{y}:\\ + ~~print~"y is true" + \end{rtbliteral} + \smallskip + +|end_example| + +|pause| +|column2| +|alert<| case y != 0 |>| +:: + + if x: + print "x is true" + print "y is true" + + +|end_alert| +|end_columns| + Promotion ================= From tverwaes at codespeak.net Thu May 8 01:24:49 2008 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Thu, 8 May 2008 01:24:49 +0200 (CEST) Subject: [pypy-svn] r54544 - pypy/extradoc/sprintinfo/berlin-2008 Message-ID: <20080507232449.D9884168056@codespeak.net> Author: tverwaes Date: Thu May 8 01:24:47 2008 New Revision: 54544 Modified: pypy/extradoc/sprintinfo/berlin-2008/people.txt Log: adding me+camillo to the sprint Modified: pypy/extradoc/sprintinfo/berlin-2008/people.txt ============================================================================== --- pypy/extradoc/sprintinfo/berlin-2008/people.txt (original) +++ pypy/extradoc/sprintinfo/berlin-2008/people.txt Thu May 8 01:24:47 2008 @@ -12,6 +12,8 @@ ==================== ============== ======================= Maciej Fijalkowski 14-22.V private Stephan Diehl ? private +Toon Verwaest 14-16-22 hotel - Die Fabrik +Camillo Bruni 14-16-22 hotel - Die Fabrik ==================== ============== ======================= People on the following list were present at previous sprints: From pedronis at codespeak.net Thu May 8 10:55:24 2008 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 8 May 2008 10:55:24 +0200 (CEST) Subject: [pypy-svn] r54545 - pypy/extradoc/sprintinfo/berlin-2008 Message-ID: <20080508085524.31118168423@codespeak.net> Author: pedronis Date: Thu May 8 10:55:23 2008 New Revision: 54545 Modified: pypy/extradoc/sprintinfo/berlin-2008/people.txt Log: my sprint dates and info Modified: pypy/extradoc/sprintinfo/berlin-2008/people.txt ============================================================================== --- pypy/extradoc/sprintinfo/berlin-2008/people.txt (original) +++ pypy/extradoc/sprintinfo/berlin-2008/people.txt Thu May 8 10:55:23 2008 @@ -14,6 +14,7 @@ Stephan Diehl ? private Toon Verwaest 14-16-22 hotel - Die Fabrik Camillo Bruni 14-16-22 hotel - Die Fabrik +Samuele Pedroni 16-21 Hotel Klassik Berlin ==================== ============== ======================= People on the following list were present at previous sprints: From arigo at codespeak.net Thu May 8 11:05:02 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 8 May 2008 11:05:02 +0200 (CEST) Subject: [pypy-svn] r54546 - in pypy/branch/gc-tweak/pypy/rpython/memory: gc test Message-ID: <20080508090502.838E1168435@codespeak.net> Author: arigo Date: Thu May 8 11:05:01 2008 New Revision: 54546 Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gc/generation.py pypy/branch/gc-tweak/pypy/rpython/memory/gc/hybrid.py pypy/branch/gc-tweak/pypy/rpython/memory/gc/semispace.py pypy/branch/gc-tweak/pypy/rpython/memory/test/test_gc.py Log: Fix a bug, with test. See comment in GenerationGC.collect_roots. Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gc/generation.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/memory/gc/generation.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/memory/gc/generation.py Thu May 8 11:05:01 2008 @@ -287,11 +287,22 @@ self.objects_with_weakrefs.append(obj) def collect_roots(self): + """GenerationGC: collects all roots. + HybridGC: collects all roots, excluding the generation 3 ones. + """ + # Warning! References from static (and possibly gen3) objects + # are found by collect_last_generation_roots(), which must be + # called *first*! If it is called after walk_roots(), then the + # HybridGC explodes if one of the _collect_root causes an object + # to be added to self.last_generation_root_objects. Indeed, in + # this case, the newly added object is traced twice: once by + # collect_last_generation_roots() and once because it was added + # in self.rawmalloced_objects_to_trace. + self.collect_last_generation_roots() self.root_walker.walk_roots( SemiSpaceGC._collect_root, # stack roots SemiSpaceGC._collect_root, # static in prebuilt non-gc structures None) # we don't need the static in prebuilt gc objects - self.collect_last_generation_roots() def collect_last_generation_roots(self): stack = self.last_generation_root_objects @@ -337,7 +348,7 @@ llarena.arena_reset(self.nursery, self.nursery_size, True) if DEBUG_PRINT: llop.debug_print(lltype.Void, "percent survived:", float(scan - beginning) / self.nursery_size) - self.debug_check_consistency() + #self.debug_check_consistency() # -- quite expensive else: # no nursery - this occurs after a full collect, triggered either # just above or by some previous non-nursery-based allocation. @@ -490,6 +501,12 @@ ll_assert(not (self.header(obj).tid & GCFLAG_NO_HEAP_PTRS), "unexpected GCFLAG_NO_HEAP_PTRS") + def debug_check_can_copy(self, obj): + if self.is_in_nursery(obj): + pass # it's ok to copy an object out of the nursery + else: + SemiSpaceGC.debug_check_can_copy(self, obj) + # ____________________________________________________________ import os Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gc/hybrid.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/memory/gc/hybrid.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/memory/gc/hybrid.py Thu May 8 11:05:01 2008 @@ -88,6 +88,8 @@ def __init__(self, *args, **kwds): large_object = kwds.pop('large_object', 24) large_object_gcptrs = kwds.pop('large_object_gcptrs', 32) + self.generation3_collect_threshold = kwds.pop( + 'generation3_collect_threshold', GENERATION3_COLLECT_THRESHOLD) GenerationGC.__init__(self, *args, **kwds) # Objects whose total size is at least 'large_object' bytes are @@ -250,12 +252,12 @@ # external objects of 3rd generation. def collect(self): - self.count_semispaceonly_collects = GENERATION3_COLLECT_THRESHOLD + self.count_semispaceonly_collects = self.generation3_collect_threshold GenerationGC.collect(self) def is_collecting_gen3(self): count = self.count_semispaceonly_collects - return count >= GENERATION3_COLLECT_THRESHOLD + return count >= self.generation3_collect_threshold # ___________________________________________________________________ # the following methods are hook into SemiSpaceGC.semispace_collect() @@ -338,12 +340,12 @@ # NB. the object can have a finalizer or be a weakref, but # it's not an issue. totalsize = self.size_gc_header() + objsize - if DEBUG_PRINT: - self._nonmoving_copy_count += 1 - self._nonmoving_copy_size += raw_malloc_usage(totalsize) newaddr = self.allocate_external_object(totalsize) if not newaddr: return llmemory.NULL # can't raise MemoryError during a collect() + if DEBUG_PRINT: + self._nonmoving_copy_count += 1 + self._nonmoving_copy_size += raw_malloc_usage(totalsize) llmemory.raw_memcopy(obj - self.size_gc_header(), newaddr, totalsize) newobj = newaddr + self.size_gc_header() Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gc/semispace.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/memory/gc/semispace.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/memory/gc/semispace.py Thu May 8 11:05:01 2008 @@ -317,6 +317,8 @@ root.address[0] = self.copy(root.address[0]) def copy(self, obj): + if self.DEBUG: + self.debug_check_can_copy(obj) if self.is_forwarded(obj): #llop.debug_print(lltype.Void, obj, "already copied to", self.get_forwarding_address(obj)) return self.get_forwarding_address(obj) @@ -586,5 +588,9 @@ ll_assert(not (tid & GCFLAG_FINALIZATION_ORDERING), "unexpected GCFLAG_FINALIZATION_ORDERING") + def debug_check_can_copy(self, obj): + ll_assert(not (self.tospace <= obj < self.free), + "copy() on already-copied object") + STATISTICS_NUMBERS = 0 Modified: pypy/branch/gc-tweak/pypy/rpython/memory/test/test_gc.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/memory/test/test_gc.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/memory/test/test_gc.py Thu May 8 11:05:01 2008 @@ -478,3 +478,46 @@ return b.num_deleted res = self.interpret(f, [15]) assert res == 16 + +class TestHybridGCSmallHeap(GCTest): + from pypy.rpython.memory.gc.hybrid import HybridGC as GCClass + GC_PARAMS = {'space_size': 192, + 'min_nursery_size': 48, + 'nursery_size': 48, + 'large_object': 12, + 'large_object_gcptrs': 12, + 'generation3_collect_threshold': 5, + } + + def test_gen3_to_gen2_refs(self): + class A(object): + def __init__(self): + self.x1 = -1 + def f(x): + loop = A() + loop.next = loop + loop.prev = loop + i = 0 + while i < x: + i += 1 + a1 = A() + a1.x1 = i + a2 = A() + a2.x1 = i + 1000 + a1.prev = loop.prev + a1.prev.next = a1 + a1.next = loop + loop.prev = a1 + a2.prev = loop + a2.next = loop.next + a2.next.prev = a2 + loop.next = a2 + i = 0 + a = loop + while True: + a = a.next + i += 1 + if a is loop: + return i + res = self.interpret(f, [200]) + assert res == 401 From antocuni at codespeak.net Thu May 8 11:36:53 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 8 May 2008 11:36:53 +0200 (CEST) Subject: [pypy-svn] r54547 - pypy/extradoc/talk/pycon-italy-2008 Message-ID: <20080508093653.3169D168442@codespeak.net> Author: antocuni Date: Thu May 8 11:36:51 2008 New Revision: 54547 Modified: pypy/extradoc/talk/pycon-italy-2008/technical.txt Log: convert all the remaining code examples; remove one slide Modified: pypy/extradoc/talk/pycon-italy-2008/technical.txt ============================================================================== --- pypy/extradoc/talk/pycon-italy-2008/technical.txt (original) +++ pypy/extradoc/talk/pycon-italy-2008/technical.txt Thu May 8 11:36:51 2008 @@ -4,10 +4,6 @@ Translation details (1) ======================= -.. raw:: html - -
- - First, load and initialize RPython code inside a normal Python VM - RPython translation starts from the resulting "live" bytecode @@ -15,9 +11,10 @@ - Unified "intermediate code" representation: a forest of *Control Flow Graphs* -.. raw:: html +.. image:: flowgraph.png + :align: right + :scale: 30 -  
Translation details (2) ======================= @@ -434,61 +431,76 @@ Promotion (example) ======================== -+----------------------------------------------------------------------------+---------------------------------------------------------------+ -| | ``def f(`` :red:`x`, :red:`y` ``):`` | | -| | :green:`x1` = ``hint(``:red:`x`, ``promote=True)`` | | ``def f_(x, y):`` | -| | ``return`` :green:`x1` ``*`` :green:`x1` ``+`` :red:`y` ``*`` :red:`y` | | ``switch x:`` | -| | | ``pass`` | -| | | ``default:`` | -| | | ``compile_more(value=x)`` | -| | | | -| +---------------------------------------------------------------+ -| | | ``def f_(x, y):`` | -| | | ``switch x:`` | -| | | *case 3:* | -| | | *return 9 + y*y* | -| | | ``default:`` | -| | | ``compile_more(value=x)`` | -| | | | -+----------------------------------------------------------------------------+---------------------------------------------------------------+ +|example<| Example |>| + +.. raw:: latex + + \smallskip + \begin{rtbliteral} + def~f(\red{x},~\red{y}):\\ + ~~\green{x1}~=~hint(\red{x},~promote=True)\\ + ~~return~\green{x1}*\green{x1}~+~\red{y}*\red{y} + \end{rtbliteral} + \smallskip + +|end_example| + +|small| +|pause| +|column1| +|alert<| original |>| +:: + + def f_(x, y): + switch x: + pass + default: + compile_more(x) + +|end_alert| + +|pause| +|column2| +|alert<| augmented |>| +:: + + def f_(x, y): + switch x: + case 3: + return 9 + y*y + default: + compile_more(x) + +|end_alert| +|end_columns| +|end_small| -Virtuals + Promotion -===================== - -* Example from PyPy (simplified!): -+----------------------------------------------------------------------------------------+ -| | ``def add_python_objects(``:red:`obj1`, :red:`obj2` ``):`` | -| | :green:`obj1cls` = ``hint(``:red:`obj1`. ``__class__, promote=True)`` | -| | :green:`obj2cls` = ``hint(``:red:`obj2`. ``__class__, promote=True)`` | -| | ``if`` :green:`obj1cls` ``is IntObject and`` :green:`obj2cls` ``is IntObject:`` | -| | :red:`x` = :red:`obj1`. ``intval`` | -| | :red:`y` = :red:`obj2`. ``intval`` | -| | :red:`z` = :red:`x` ``+`` :red:`y` | -| | ``return IntObject(intval=``:red:`z` ``)`` | -+----------------------------------------------------------------------------------------+ Virtuals + Promotion ===================== -| *The factorial for the Toy Language interpreter:* -| ``PUSH 1 # accumulator`` -| ``PUSHARG`` -| ``start:`` -| ``PICK 0`` -| ``PUSH 1`` -| ``LE`` -| ``BR_COND exit`` -| ``SWAP`` -| ``PICK 1`` -| ``MUL`` -| ``SWAP`` -| ``PUSH 1`` -| ``SUB`` -| ``PUSH 1`` -| ``BR_COND start`` +|small| +|example<| Example from PyPy (simplified!) |>| + +.. raw:: latex + + \smallskip + \begin{rtbliteral} + def~add\_python\_objects(\red{obj1},~\red{obj2}):\\ + ~~\green{obj1cls}~=~hint(\red{obj1}.\_\_class\_\_,~promote=True)\\ + ~~\green{obj2cls}~=~hint(\red{obj2}.\_\_class\_\_,~promote=True)\\ + ~~if~\green{obj1cls}~is~IntObject~and~\green{obj2cls}~is~IntObject:\\ + ~~~~\red{x}~=~\red{obj1}.intval\\ + ~~~~\red{y}~=~\red{obj2}.intval\\ + ~~~~\red{z}~=~\red{x}~+~\red{y}\\ + ~~~~return~IntObject(intval=\red{z})\\ + \end{rtbliteral} + \smallskip + +|end_example| +|end_small| -.. tlc example results Conclusion (JIT) ================ @@ -516,6 +528,8 @@ - more hints needed in PyPy's Python +- JIT backends for CLI/JVM + Virtualizable Frames ====================== From cfbolz at codespeak.net Thu May 8 11:45:45 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 8 May 2008 11:45:45 +0200 (CEST) Subject: [pypy-svn] r54548 - pypy/extradoc/talk/s3-2008 Message-ID: <20080508094545.081CE16842E@codespeak.net> Author: cfbolz Date: Thu May 8 11:45:43 2008 New Revision: 54548 Added: pypy/extradoc/talk/s3-2008/Makefile pypy/extradoc/talk/s3-2008/beamerouterthememy.sty pypy/extradoc/talk/s3-2008/beamerthemeWarsaw.sty pypy/extradoc/talk/s3-2008/talk.tex Log: set up the latex files for the s3 talk Added: pypy/extradoc/talk/s3-2008/Makefile ============================================================================== --- (empty file) +++ pypy/extradoc/talk/s3-2008/Makefile Thu May 8 11:45:43 2008 @@ -0,0 +1,12 @@ +%.pdf: %.eps + epstopdf $< + +viewtalk: talk.pdf + evince talk.pdf & + +clean: + rm talk.pdf + +talk.pdf: talk.tex beamerouterthememy.sty beamerthemeWarsaw.sty + pdflatex talk + Added: pypy/extradoc/talk/s3-2008/beamerouterthememy.sty ============================================================================== --- (empty file) +++ pypy/extradoc/talk/s3-2008/beamerouterthememy.sty Thu May 8 11:45:43 2008 @@ -0,0 +1,39 @@ +\ProvidesPackageRCS $Header: /cvsroot/latex-beamer/latex-beamer/themes/outer/beamerouterthemesplit.sty,v 1.4 2004/10/07 22:21:16 tantau Exp $ + +% Copyright 2003 by Till Tantau +% +% This program can be redistributed and/or modified under the terms +% of the GNU Public License, version 2. + +\mode + +\setbeamercolor{section in head/foot}{parent=palette quaternary} +\setbeamercolor{subsection in head/foot}{parent=palette primary} + +\setbeamercolor{author in head/foot}{parent=section in head/foot} +\setbeamercolor{title in head/foot}{parent=subsection in head/foot} + + + +\usesectionheadtemplate + {\hfill\insertsectionhead} + {\hfill\color{fg!50!bg}\insertsectionhead} + + + + +\defbeamertemplate*{footline}{split theme} +{% + \leavevmode% + \hbox{\begin{beamercolorbox}[wd=.5\paperwidth,ht=2.5ex,dp=1.125ex,leftskip=.3cm plus1fill,rightskip=.3cm]{author in head/foot}% + \usebeamerfont{author in head/foot}\insertshortauthor + \end{beamercolorbox}% + \begin{beamercolorbox}[wd=.5\paperwidth,ht=2.5ex,dp=1.125ex,leftskip=.3cm,rightskip=.3cm plus1fil]{title in head/foot}% + \usebeamerfont{title in head/foot}\insertshorttitle + \end{beamercolorbox}}% + \vskip0pt% +} + + +\mode + Added: pypy/extradoc/talk/s3-2008/beamerthemeWarsaw.sty ============================================================================== --- (empty file) +++ pypy/extradoc/talk/s3-2008/beamerthemeWarsaw.sty Thu May 8 11:45:43 2008 @@ -0,0 +1,18 @@ +\ProvidesPackageRCS $Header: /cvsroot/latex-beamer/latex-beamer/themes/theme/beamerthemeWarsaw.sty,v 1.8 2004/10/07 20:53:10 tantau Exp $ + +% Copyright 2003 by Till Tantau +% +% This program can be redistributed and/or modified under the terms +% of the GNU Public License, version 2. + +\mode + +\useinnertheme[shadow=true]{rounded} +\useoutertheme{my} +\usecolortheme{orchid} +\usecolortheme{whale} + +\setbeamerfont{block title}{size={}} + +\mode + Added: pypy/extradoc/talk/s3-2008/talk.tex ============================================================================== --- (empty file) +++ pypy/extradoc/talk/s3-2008/talk.tex Thu May 8 11:45:43 2008 @@ -0,0 +1,73 @@ +\documentclass[utf8x]{beamer} + +\mode +{ + \usetheme{Warsaw} + + %\setbeamercovered{transparent} +} + + +\usepackage[english]{babel} + +\usepackage[utf8x]{inputenc} + +\usepackage{times} +\usepackage[T1]{fontenc} + +\title{Back to the Future in one Week --- Implementing a Smalltalk VM in PyPy} + +\author{Carl Friedrich Bolz, Adrian Kuhn, Adrian Lienhard, Nicholas D. Matsakis, Oscar Nierstrasz, Lukas Renggli, Armin Rigo, Toon Verwaest} + + +\date{Workshop on Self-sustaining Systems, May 16 2008} + + +% Delete this, if you do not want the table of contents to pop up at +% the beginning of each subsection: +%\AtBeginSubsection[] +%{ +% \begin{frame} +% \frametitle{Outline} +% \tableofcontents[currentsection,currentsubsection] +% \end{frame} +%} + + +% If you wish to uncover everything in a step-wise fashion, uncomment +% the following command: + +%\beamerdefaultoverlayspecification{<+->} + + +\begin{document} + +\begin{frame} + \titlepage +\end{frame} + +%\begin{frame} +% \frametitle{Outline} +% \tableofcontents + % You might wish to add the option [pausesections] +%\end{frame} + +\begin{frame} + \frametitle{Scope} + This talk is about: XXX + \begin{itemize} + \item + writing a Squeak implementation + \item + with eight people + \item + in five days + \item + using PyPy +\end{frame} + + + +\end{document} + + From arigo at codespeak.net Thu May 8 11:51:26 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 8 May 2008 11:51:26 +0200 (CEST) Subject: [pypy-svn] r54549 - pypy/extradoc/sprintinfo/berlin-2008 Message-ID: <20080508095126.C7D3B168461@codespeak.net> Author: arigo Date: Thu May 8 11:51:26 2008 New Revision: 54549 Modified: pypy/extradoc/sprintinfo/berlin-2008/people.txt Log: My dates. Modified: pypy/extradoc/sprintinfo/berlin-2008/people.txt ============================================================================== --- pypy/extradoc/sprintinfo/berlin-2008/people.txt (original) +++ pypy/extradoc/sprintinfo/berlin-2008/people.txt Thu May 8 11:51:26 2008 @@ -15,6 +15,7 @@ Toon Verwaest 14-16-22 hotel - Die Fabrik Camillo Bruni 14-16-22 hotel - Die Fabrik Samuele Pedroni 16-21 Hotel Klassik Berlin +Armin Rigo 14-22(noon) private, thanks Stephan ==================== ============== ======================= People on the following list were present at previous sprints: From cfbolz at codespeak.net Thu May 8 11:53:10 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 8 May 2008 11:53:10 +0200 (CEST) Subject: [pypy-svn] r54550 - pypy/extradoc/sprintinfo/berlin-2008 Message-ID: <20080508095310.B7318168435@codespeak.net> Author: cfbolz Date: Thu May 8 11:53:10 2008 New Revision: 54550 Modified: pypy/extradoc/sprintinfo/berlin-2008/people.txt Log: my dates Modified: pypy/extradoc/sprintinfo/berlin-2008/people.txt ============================================================================== --- pypy/extradoc/sprintinfo/berlin-2008/people.txt (original) +++ pypy/extradoc/sprintinfo/berlin-2008/people.txt Thu May 8 11:53:10 2008 @@ -16,6 +16,7 @@ Camillo Bruni 14-16-22 hotel - Die Fabrik Samuele Pedroni 16-21 Hotel Klassik Berlin Armin Rigo 14-22(noon) private, thanks Stephan +Carl Friedrich Bolz 14-22 Die Fabrik ==================== ============== ======================= People on the following list were present at previous sprints: @@ -51,7 +52,6 @@ Alexandre Fayolle ? ? Sylvain Th?nault ? ? Armin Rigo ? ? -Carl Friedrich Bolz ? ? Antonio Cuni ? ? Toby Watson ? ? Paul deGrandis ? ? From antocuni at codespeak.net Thu May 8 11:55:52 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 8 May 2008 11:55:52 +0200 (CEST) Subject: [pypy-svn] r54551 - pypy/extradoc/talk/pycon-italy-2008 Message-ID: <20080508095552.CEA7D168435@codespeak.net> Author: antocuni Date: Thu May 8 11:55:52 2008 New Revision: 54551 Added: pypy/extradoc/talk/pycon-italy-2008/pypy-vm.pdf.info pypy/extradoc/talk/pycon-italy-2008/pypy-vm.txt (contents, props changed) Modified: pypy/extradoc/talk/pycon-italy-2008/makepdf pypy/extradoc/talk/pycon-italy-2008/motivation.txt pypy/extradoc/talk/pycon-italy-2008/technical.txt Log: rename the main file; add a .info file for keyjnote Modified: pypy/extradoc/talk/pycon-italy-2008/makepdf ============================================================================== --- pypy/extradoc/talk/pycon-italy-2008/makepdf (original) +++ pypy/extradoc/talk/pycon-italy-2008/makepdf Thu May 8 11:55:52 2008 @@ -3,7 +3,7 @@ # WARNING: to work, it needs this patch for docutils # https://sourceforge.net/tracker/?func=detail&atid=422032&aid=1459707&group_id=38414 -rst2beamer.py --stylesheet=stylesheet.latex --documentoptions=14pt motivation.txt motivation.latex || exit -sed 's/\\date{}/\\input{author.latex}/' -i motivation.latex || exit -pdflatex motivation.latex || exit +rst2beamer.py --stylesheet=stylesheet.latex --documentoptions=14pt pypy-vm.txt pypy-vm.latex || exit +sed 's/\\date{}/\\input{author.latex}/' -i pypy-vm.latex || exit +pdflatex pypy-vm.latex || exit Modified: pypy/extradoc/talk/pycon-italy-2008/motivation.txt ============================================================================== --- pypy/extradoc/talk/pycon-italy-2008/motivation.txt (original) +++ pypy/extradoc/talk/pycon-italy-2008/motivation.txt Thu May 8 11:55:52 2008 @@ -1,9 +1,3 @@ -.. include:: beamerdefs.txt - -PyPy and The Art of Generating Virtual Machines -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - PyPy ================== @@ -164,4 +158,4 @@ -.. include:: technical.txt + Added: pypy/extradoc/talk/pycon-italy-2008/pypy-vm.pdf.info ============================================================================== --- (empty file) +++ pypy/extradoc/talk/pycon-italy-2008/pypy-vm.pdf.info Thu May 8 11:55:52 2008 @@ -0,0 +1,11 @@ +AvailableTransitions=[Crossfade] +TransitionDuration = 100 +EstimatedDuration = 25*60 +MinutesOnly = True + +PageProps = { + 1: { + 'reset': FirstTimeOnly, + 'progress': False, + }, +} Added: pypy/extradoc/talk/pycon-italy-2008/pypy-vm.txt ============================================================================== --- (empty file) +++ pypy/extradoc/talk/pycon-italy-2008/pypy-vm.txt Thu May 8 11:55:52 2008 @@ -0,0 +1,7 @@ +.. include:: beamerdefs.txt + +PyPy and The Art of Generating Virtual Machines +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. include:: motivation.txt +.. include:: technical.txt Modified: pypy/extradoc/talk/pycon-italy-2008/technical.txt ============================================================================== --- pypy/extradoc/talk/pycon-italy-2008/technical.txt (original) +++ pypy/extradoc/talk/pycon-italy-2008/technical.txt Thu May 8 11:55:52 2008 @@ -505,12 +505,15 @@ Conclusion (JIT) ================ -Effective dynamic compiler generation make flexibility and ease of -evolution mostly **orthogonal to the performance question**. +- Effective dynamic compiler generation -Implementers are free to implement languages as **understandable interpreters**. + * flexibility and ease of evolution -PyPy proves this a viable approach worth of further exploration. + * **orthogonal to the performance question**. + +- Languages implemented as **understandable interpreters**. + +- PyPy proves this a viable approach worth of further exploration. .. backend material: not for the general talk From antocuni at codespeak.net Thu May 8 11:58:51 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 8 May 2008 11:58:51 +0200 (CEST) Subject: [pypy-svn] r54552 - pypy/extradoc/talk/pycon-italy-2008 Message-ID: <20080508095851.E905F168462@codespeak.net> Author: antocuni Date: Thu May 8 11:58:51 2008 New Revision: 54552 Added: pypy/extradoc/talk/pycon-italy-2008/pypy-vm.pdf Modified: pypy/extradoc/talk/pycon-italy-2008/author.latex Log: add a short title for beamer; generate pdf Modified: pypy/extradoc/talk/pycon-italy-2008/author.latex ============================================================================== --- pypy/extradoc/talk/pycon-italy-2008/author.latex (original) +++ pypy/extradoc/talk/pycon-italy-2008/author.latex Thu May 8 11:58:51 2008 @@ -1,6 +1,6 @@ \definecolor{rrblitbackground}{rgb}{0.0, 0.0, 0.0} -\title{PyPy and The Art of Generating Virtual Machines} +\title[PyPy and The Art of Generating VMs]{PyPy and The Art of Generating Virtual Machines} \author[Antonio Cuni]{Antonio Cuni\\DISI, Universit? degli Studi di Genova} \institute[PyCon Due 2008]{PyCon Due 2008 - Firenze} \date{May 10, 2008} Added: pypy/extradoc/talk/pycon-italy-2008/pypy-vm.pdf ============================================================================== Files (empty file) and pypy/extradoc/talk/pycon-italy-2008/pypy-vm.pdf Thu May 8 11:58:51 2008 differ From arigo at codespeak.net Thu May 8 12:45:55 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 8 May 2008 12:45:55 +0200 (CEST) Subject: [pypy-svn] r54553 - pypy/extradoc/talk/pycon-italy-2008 Message-ID: <20080508104555.49EC2168423@codespeak.net> Author: arigo Date: Thu May 8 12:45:53 2008 New Revision: 54553 Modified: pypy/extradoc/talk/pycon-italy-2008/technical.txt Log: Typos. Otherwise, it looks good, I think. Modified: pypy/extradoc/talk/pycon-italy-2008/technical.txt ============================================================================== --- pypy/extradoc/talk/pycon-italy-2008/technical.txt (original) +++ pypy/extradoc/talk/pycon-italy-2008/technical.txt Thu May 8 12:45:53 2008 @@ -315,7 +315,7 @@ * The rainbow interpreter executes the bytecode -* As a result, it procude executable code +* As a result, it produces executable code |end_example| @@ -424,7 +424,7 @@ the compiler with runtime values. * On callback the compiler adds one more case to the switch and - generate more code assuming the received value. + generates more code assuming the received value. .. need to save state in a compact form: paths From arigo at codespeak.net Thu May 8 13:26:22 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 8 May 2008 13:26:22 +0200 (CEST) Subject: [pypy-svn] r54554 - pypy/branch/gc-tweak/pypy/rpython/memory/gc/test Message-ID: <20080508112622.857522D8008@codespeak.net> Author: arigo Date: Thu May 8 13:26:22 2008 New Revision: 54554 Added: pypy/branch/gc-tweak/pypy/rpython/memory/gc/test/test_direct.py (contents, props changed) Log: Starting some direct GC tests that can run without the llinterpreter at all. Added: pypy/branch/gc-tweak/pypy/rpython/memory/gc/test/test_direct.py ============================================================================== --- (empty file) +++ pypy/branch/gc-tweak/pypy/rpython/memory/gc/test/test_direct.py Thu May 8 13:26:22 2008 @@ -0,0 +1,120 @@ +""" The tests below don't use translation at all. They run the GCs by +instantiating them and asking them to allocate memory by calling their +methods directly. The tests need to maintain by hand what the GC should +see as the list of roots (stack and prebuilt objects). +""" + +import py +from pypy.rpython.lltypesystem import lltype, llmemory +from pypy.rpython.memory.gctypelayout import TypeLayoutBuilder + +ADDR_ARRAY = lltype.Array(llmemory.Address) +S = lltype.GcForwardReference() +S.become(lltype.GcStruct('S', + ('x', lltype.Signed), + ('next', lltype.Ptr(S)))) + + +class DirectRootWalker(object): + + def __init__(self, tester): + self.tester = tester + + def walk_roots(self, collect_stack_root, + collect_static_in_prebuilt_nongc, + collect_static_in_prebuilt_gc): + gc = self.tester.gc + layoutbuilder = self.tester.layoutbuilder + if collect_static_in_prebuilt_gc: + for addrofaddr in layoutbuilder.addresses_of_static_ptrs: + if addrofaddr.address[0]: + collect_static_in_prebuilt_gc(gc, addrofaddr) + if collect_static_in_prebuilt_nongc: + for addrofaddr in layoutbuilder.addresses_of_static_ptrs_in_nongc: + if addrofaddr.address[0]: + collect_static_in_prebuilt_nongc(gc, addrofaddr) + if collect_stack_root: + stackroots = self.tester.stackroots + a = lltype.malloc(ADDR_ARRAY, len(stackroots), flavor='raw') + for i in range(len(a)): + a[i] = llmemory.cast_ptr_to_adr(stackroots[i]) + a_base = lltype.direct_arrayitems(a) + for i in range(len(a)): + ai = lltype.direct_ptradd(a_base, i) + collect_stack_root(gc, llmemory.cast_ptr_to_adr(ai)) + for i in range(len(a)): + PTRTYPE = lltype.typeOf(stackroots[i]) + stackroots[i] = llmemory.cast_adr_to_ptr(a[i], PTRTYPE) + lltype.free(a, flavor='raw') + + def _walk_prebuilt_gc(self, callback): + pass + + +class DirectGCTest(object): + GC_PARAMS = {} + + def setup_method(self, meth): + self.stackroots = [] + self.gc = self.GCClass(**self.GC_PARAMS) + self.gc.DEBUG = True + self.rootwalker = DirectRootWalker(self) + self.gc.set_root_walker(self.rootwalker) + self.layoutbuilder = TypeLayoutBuilder() + self.get_type_id = self.layoutbuilder.get_type_id + self.layoutbuilder.initialize_gc_query_function(self.gc) + self.gc.setup() + + def consider_constant(self, p): + obj = p._obj + TYPE = lltype.typeOf(obj) + self.layoutbuilder.consider_constant(TYPE, obj, self.gc) + + def write(self, p, fieldname, newvalue): + if self.gc.needs_write_barrier: + oldaddr = llmemory.cast_ptr_to_adr(getattr(p, fieldname)) + newaddr = llmemory.cast_ptr_to_adr(newvalue) + addr_struct = llmemory.cast_ptr_to_adr(p) + self.gc.write_barrier(oldaddr, newaddr, addr_struct) + setattr(p, fieldname, newvalue) + + def malloc(self, TYPE): + addr = self.gc.malloc(self.get_type_id(TYPE)) + return llmemory.cast_adr_to_ptr(addr, lltype.Ptr(TYPE)) + + def test_simple(self): + p = self.malloc(S) + p.x = 5 + self.stackroots.append(p) + self.gc.collect() + p = self.stackroots[0] + assert p.x == 5 + + def test_missing_stack_root(self): + p = self.malloc(S) + p.x = 5 + self.gc.collect() # 'p' should go away + py.test.raises(RuntimeError, 'p.x') + + def test_prebuilt_gc(self): + k = lltype.malloc(S, immortal=True) + k.x = 42 + self.consider_constant(k) + self.write(k, 'next', self.malloc(S)) + k.next.x = 43 + self.write(k.next, 'next', self.malloc(S)) + k.next.next.x = 44 + self.gc.collect() + assert k.x == 42 + assert k.next.x == 43 + assert k.next.next.x == 44 + + +class TestSemiSpaceGC(DirectGCTest): + from pypy.rpython.memory.gc.semispace import SemiSpaceGC as GCClass + +class TestGenerationGC(TestSemiSpaceGC): + from pypy.rpython.memory.gc.generation import GenerationGC as GCClass + +class TestHybridGC(TestGenerationGC): + from pypy.rpython.memory.gc.hybrid import HybridGC as GCClass From arigo at codespeak.net Thu May 8 13:40:52 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 8 May 2008 13:40:52 +0200 (CEST) Subject: [pypy-svn] r54555 - pypy/branch/gc-tweak/pypy/rpython/memory/gc/test Message-ID: <20080508114052.D655B1684E5@codespeak.net> Author: arigo Date: Thu May 8 13:40:50 2008 New Revision: 54555 Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gc/test/test_direct.py Log: A couple of extra tests. Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gc/test/test_direct.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/memory/gc/test/test_direct.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/memory/gc/test/test_direct.py Thu May 8 13:40:50 2008 @@ -4,6 +4,8 @@ see as the list of roots (stack and prebuilt objects). """ +# XXX VERY INCOMPLETE, low coverage + import py from pypy.rpython.lltypesystem import lltype, llmemory from pypy.rpython.memory.gctypelayout import TypeLayoutBuilder @@ -12,7 +14,9 @@ S = lltype.GcForwardReference() S.become(lltype.GcStruct('S', ('x', lltype.Signed), + ('prev', lltype.Ptr(S)), ('next', lltype.Ptr(S)))) +RAW = lltype.Struct('RAW', ('p', lltype.Ptr(S)), ('q', lltype.Ptr(S))) class DirectRootWalker(object): @@ -109,6 +113,67 @@ assert k.next.x == 43 assert k.next.next.x == 44 + def test_prebuilt_nongc(self): + raw = lltype.malloc(RAW, immortal=True) + self.consider_constant(raw) + raw.p = self.malloc(S) + raw.p.x = 43 + raw.q = self.malloc(S) + raw.q.x = 44 + self.gc.collect() + assert raw.p.x == 43 + assert raw.q.x == 44 + + def test_many_objects(self): + + def alloc2(i): + a1 = self.malloc(S) + a1.x = i + self.stackroots.append(a1) + a2 = self.malloc(S) + a1 = self.stackroots.pop() + a2.x = i + 1000 + return a1, a2 + + def growloop(loop, a1, a2): + self.write(a1, 'prev', loop.prev) + self.write(a1.prev, 'next', a1) + self.write(a1, 'next', loop) + self.write(loop, 'prev', a1) + self.write(a2, 'prev', loop) + self.write(a2, 'next', loop.next) + self.write(a2.next, 'prev', a2) + self.write(loop, 'next', a2) + + def newloop(): + p = self.malloc(S) + p.next = p # initializing stores, no write barrier + p.prev = p + return p + + # a loop attached to a stack root + self.stackroots.append(newloop()) + + # another loop attached to a prebuilt gc node + k = lltype.malloc(S, immortal=True) + k.next = k + k.prev = k + self.consider_constant(k) + + # a third loop attached to a prebuilt nongc + raw = lltype.malloc(RAW, immortal=True) + self.consider_constant(raw) + raw.p = newloop() + + # run! + for i in range(100): + a1, a2 = alloc2(i) + growloop(self.stackroots[0], a1, a2) + a1, a2 = alloc2(i) + growloop(k, a1, a2) + a1, a2 = alloc2(i) + growloop(raw.p, a1, a2) + class TestSemiSpaceGC(DirectGCTest): from pypy.rpython.memory.gc.semispace import SemiSpaceGC as GCClass From cami at codespeak.net Thu May 8 13:54:15 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Thu, 8 May 2008 13:54:15 +0200 (CEST) Subject: [pypy-svn] r54556 - in pypy/branch/gameboy-emulator/pypy/lang/gameboy: . test Message-ID: <20080508115415.1D5ED1684ED@codespeak.net> Author: cami Date: Thu May 8 13:54:14 2008 New Revision: 54556 Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboy.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboyImplementation.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/interrupt.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/joypad.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/serial.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cartridge.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cpu.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_interrupt.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_joypad.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_register.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_rom.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_serial.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_timer.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/timer.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/video.py Log: updated functions name by transforming all camelcase names to python-like underscore names updated test aswell Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py Thu May 8 13:54:14 2008 @@ -4,7 +4,7 @@ from pypy.lang.gameboy import constants import os -def hasCartridgeBattery(self, cartridgeType): +def has_cartridge_battery(self, cartridgeType): return (cartridgeType == constants.TYPE_MBC1_RAM_BATTERY \ or cartridgeType == constants.TYPE_MBC2_BATTERY \ or cartridgeType == constants.TYPE_MBC3_RTC_BATTERY \ @@ -14,11 +14,9 @@ or cartridgeType == constants.TYPE_MBC5_RUMBLE_RAM_BATTERY \ or cartridgeType == constants.TYPE_HUC1_RAM_BATTERY) -def hasCartridgeType(self, catridgeType): - return constants.CATRIDGE_TYPE_MAPPING.has_key(cartridgeType) -def createBankController(self, cartridgeType, rom, ram, clock): - if hasCartridgeType(cartridgeType): +def create_bank_controller(self, cartridgeType, rom, ram, clock): + if constants.CATRIDGE_TYPE_MAPPING.has_key(cartridgeType) : return constants.CATRIDGE_TYPE_MAPPING[cartridgeType](rom, ram, clock) else: raise InvalidMemoryBankTypeError("Unsupported memory bank controller (0x"+hex(cartridgeType)+")") @@ -38,7 +36,7 @@ self.cartridge = None def reset(self): - if not self.hasBattery(): + if not self.has_battery(): self.ram[0:len(self.ram):1] = 0xFF self.mbc.reset() @@ -51,85 +49,85 @@ def load(self, cartridge): self.cartridge = cartridge self.rom = self.cartridge.read() - self.checkROM() - self.createRAM() - self.loadBattery() - self.mbc = self.createBankController(self.getMemoryBankType(), self.rom, self.ram, self.clock) + self.check_rom() + self.create_ram() + self.load_battery() + self.mbc = self.create_bank_controller(self.get_memory_bank_type(), self.rom, self.ram, self.clock) - def checkROM(self): - if not self.verifyHeader(): + def check_rom(self): + if not self.verify_header(): raise Exeption("Cartridge header is corrupted") - if self.cartridge.getSize() < self.getROMSize(): + if self.cartridge.get_size() < self.get_rom_size(): raise Exeption("Cartridge is truncated") - def createRAM(self): - ramSize = self.getRAMSize() - if self.getMemoryBankType() >= constants.TYPE_MBC2 \ - and self.getMemoryBankType() <= constants.TYPE_MBC2_BATTERY: + def create_ram(self): + ramSize = self.get_ram_size() + if self.get_memory_bank_type() >= constants.TYPE_MBC2 \ + and self.get_memory_bank_type() <= constants.TYPE_MBC2_BATTERY: ramSize = 512 self.ram = [0xFF]*ramSize - def loadBattery(self): - if self.cartridge.hasBattery(): - self.ram = self.cartridge.readBattery() + def load_battery(self): + if self.cartridge.has_battery(): + self.ram = self.cartridge.read_battery() def save(self, cartridgeName): - if self.cartridge.hasBattery(): - self.cartridge.writeBattery(self.ram) + if self.cartridge.has_battery(): + self.cartridge.write_battery(self.ram) - def getMemoryBankType(self): + def get_memory_bank_type(self): return self.rom[constants.CARTRIDGE_TYPE_ADDRESS] & 0xFF - def getMemoryBank(self): + def get_memory_bank(self): return self.mbc - def getROM(self): + def get_rom(self): return self.rom - def getROMSize(self): + def get_rom_size(self): romSize = self.rom[constants.CARTRIDGE_ROM_SIZE_ADDRESS] & 0xFF if romSize>=0x00 and romSize<=0x07: return 32768 << romSize return -1 - def getRAMSize(self): + def get_ram_size(self): return constants.CARTRIDGE_RAM_SIZE_MAPPING[self.rom[constants.CARTRIDGE_RAM_SIZE_ADDRESS]] - def getDestinationCode(self): + def get_destination_code(self): return self.rom[constants.DESTINATION_CODE_ADDRESS] & 0xFF - def getLicenseeCode(): + def get_licensee_code(): return self.rom[constants.LICENSEE_ADDRESS] & 0xFF - def getROMVersion(self): + def get_rom_version(self): return self.rom[constants.CARTRIDGE_ROM_VERSION_ADDRESS] & 0xFF - def getHeaderChecksum(self): + def get_header_checksum(self): return self.rom[constants.HEADER_CHECKSUM_ADDRESS] & 0xFF - def getChecksum(self): + def get_checksum(self): return ((self.rom[constants.CHECKSUM_A_ADDRESS] & 0xFF) << 8) \ + (self.rom[constants.CHECKSUM_B_ADDRESS] & 0xFF) - def hasBattery(self): - return hasCartridgeBattery(self.getMemoryBankType()) + def has_battery(self): + return has_cartridge_battery(self.getMemoryBankType()) def verify(self): checksum = 0 for address in range(len(self.rom)): if address is not 0x014E and address is not 0x014F: checksum = (checksum + (self.rom[address] & 0xFF)) & 0xFFFF - return (checksum == self.getChecksum()) + return (checksum == self.get_checksum()) - def verifyHeader(self): + def verify_header(self): if len(self.rom) < 0x0150: return False checksum = 0xE7 for address in range(0x0134, 0x014C): checksum = (checksum - (self.rom[address] & 0xFF)) & 0xFF - return (checksum == self.getHeaderChecksum()) + return (checksum == self.get_header_checksum()) - def createBankController(self, type, rom, ram, clockDriver): + def create_bank_controller(self, type, rom, ram, clockDriver): return MEMORY_BANK_MAPPING[type](rom, ram, clockDriver) @@ -158,16 +156,16 @@ self.cartridgeFilePath = cartridgeFilePath self.cartridgeName = os.path.basename(cartridgeFilePath) self.cartridgeFile = open(cartridgeFilePath) - self._loadBattery(cartridgeFilePath) + self._load_battery(cartridgeFilePath) - def _loadBattery(self, cartridgeFilePath): - self.batteryFilePath = self._createBatteryFilePath(cartridgeFilePath) + def _load_battery(self, cartridgeFilePath): + self.batteryFilePath = self._create_battery_file_path(cartridgeFilePath) self.batteryName = os.path.basename(self.batteryFilePath) - if self.hasBattery(): + if self.has_battery(): self.batteryFile = open(self.batteryFilePath) - def _createBatteryFilePath(self, cartridgeFilePath): + def _create_battery_file_path(self, cartridgeFilePath): if cartridgeFilePath.endswith(constants.CARTRIDGE_FILE_EXTENSION): return cartridgeFilePath.replace(constants.CARTRIDGE_FILE_EXTENSION, constants.BATTERY_FILE_EXTENSION) @@ -177,30 +175,30 @@ else: return cartridgeFilePath + constants.BATTERY_FILE_EXTENSION - def hasBattery(self): + def has_battery(self): return os.path.exists(self.batteryFilePath) def read(self): self.cartridgeFile.seek(0) return map(map_to_byte, self.cartridgeFile.read()) - def readBattery(self): + def read_battery(self): self.batteryFile.seek(0) return map(map_to_byte, self.batteryFile.read()) - def writeBattery(self, ram): + def write_battery(self, ram): self.batteryFile = open(self.batteryFilePath, "w") self.batteryFile.write(("").join(map(chr, ram))) self.batteryFile = open(self.batteryFilePath, "r+") - def removeBattery(self): - if self.hasBattery(): + def remove_battery(self): + if self.has_battery(): os.remove(self.batteryFilePath) - def getSize(self): + def get_size(self): return os.path.getsize(self.cartridgeFilePath) - def getBatterySize(self): + def get_battery_size(self): return os.path.getsize(self.batteryFilePath) @@ -214,8 +212,8 @@ class MBC(object): def __init__(self, rom, ram, clockDriver): - self.setROM(rom) - self.setRAM(ram) + self.set_rom(rom) + self.set_ram(ram) def reset(self): self.romBank = constants.ROM_BANK_SIZE @@ -230,7 +228,7 @@ self.minRamBankSize = 0 self.maxRamBankSize = 0 - def setROM(self, buffer): + def set_rom(self, buffer): banks = len(buffer) / constants.ROM_BANK_SIZE if banks < self.minRomBankSize or banks > self.maxRomBankSize: raise Exception("Invalid constants.ROM size") @@ -238,7 +236,7 @@ self.romSize = constants.ROM_BANK_SIZE*banks - 1 - def setRAM(self, buffer): + def set_ram(self, buffer): banks = len(buffer) / constants.RAM_BANK_SIZE if banks < self.minRamBankSize or banks > self.maxRamBankSize: raise Exception("Invalid constants.RAM size") @@ -301,21 +299,21 @@ def write(self, address, data): if address <= 0x1FFF: # 0000-1FFF - self.writeRAMEnable(address, data) + self.write_ram_enable(address, data) elif address <= 0x3FFF: # 2000-3FFF - self.writeROMBank1(address, data) + self.write_rom_bank_1(address, data) elif address <= 0x5FFF: # 4000-5FFF - self.writeROMBank2(address, data) + self.write_rom_bank_2(address, data) elif address <= 0x7FFF: # 6000-7FFF self.memoryModel = data & 0x01 elif address >= 0xA000 and address <= 0xBFFF and self.ramEnable: # A000-BFFF self.ram[self.ramBank + (address & 0x1FFF)] = data - def writeRAMEnable(self, address, data): + def write_ram_enable(self, address, data): if self.ramSize > 0: self.ramEnable = ((data & 0x0A) == 0x0A) - def writeROMBank1(self, address, data): + def write_rom_bank_1(self, address, data): if (data & 0x1F) == 0: data = 1 if self.memoryModel == 0: @@ -323,7 +321,7 @@ else: self.romBank = ((data & 0x1F) << 14) & self.romSize - def writeROMBank2(self, address, data): + def write_rom_bank_2(self, address, data): if self.memoryModel == 0: self.romBank = ((self.romBank & 0x07FFFF) + ((data & 0x03) << 19)) & self.romSize else: @@ -363,24 +361,24 @@ def write(self, address, data): if address <= 0x1FFF: # 0000-1FFF - self.writeRAMEnable(address, data) + self.write_ram_enable(address, data) elif address <= 0x3FFF: # 2000-3FFF - self.writeROMBank() + self.write_rom_bank() elif address >= 0xA000 and address <= 0xA1FF: # A000-A1FF - self.writeRAMEnable(address, data) + self.write_ram(address, data) - def writeRAMEnable(self, address, data): + def write_ram_enable(self, address, data): if (address & 0x0100) == 0: self.ramEnable = ((data & 0x0A) == 0x0A) - def writeROMBank(self, address): + def write_rom_bank(self, address): if (address & 0x0100) == 0: return if (data & 0x0F) == 0: data = 1 self.romBank = ((data & 0x0F) << 14) & self.romSize - def writeRAM(self, address, data): + def write_ram(self, address, data): if self.ramEnable: self.ram[address & 0x01FF] = data & 0x0F @@ -425,74 +423,74 @@ if (self.ramBank >= 0): return self.ram[self.ramBank + (address & 0x1FFF)] & 0xFF else: - return self.readClockData(address) + return self.read_clock_data(address) else: return super.read(address) - def readClockDaata(self, address): - if (self.clockRegister == 0x08): + def read_clock_data(self, address): + if self.clockRegister == 0x08: return self.clockLSeconds - if (self.clockRegister == 0x09): + if self.clockRegister == 0x09: return self.clockLMinutes - if (self.clockRegister == 0x0A): + if self.clockRegister == 0x0A: return self.clockLHours - if (self.clockRegister == 0x0B): + if self.clockRegister == 0x0B: return self.clockLDays - if (self.clockRegister == 0x0C): + if self.clockRegister == 0x0C: return self.clockLControl def write(self, address, data): - if (address <= 0x1FFF): # 0000-1FFF - self.writeRAMEnable(address, data) - elif (address <= 0x3FFF): # 2000-3FFF - self.writeROMBank(address, data) - elif (address <= 0x5FFF): # 4000-5FFF - self.writeRAMBank(address, data) - elif (address <= 0x7FFF): # 6000-7FFF - self.writeClockLatch(address, data) - elif (address >= 0xA000 and address <= 0xBFFF and self.ramEnable): # A000-BFFF - self.writeClockData(address, data) + if address <= 0x1FFF: # 0000-1FFF + self.write_ram_enable(address, data) + elif address <= 0x3FFF: # 2000-3FFF + self.write_rom_bank(address, data) + elif address <= 0x5FFF: # 4000-5FFF + self.write_ram_bank(address, data) + elif address <= 0x7FFF: # 6000-7FFF + self.write_clock_latch(address, data) + elif address >= 0xA000 and address <= 0xBFFF and self.ramEnable: # A000-BFFF + self.write_clock_data(address, data) - def writeRAMEnable(self, address, data): + def write_ram_enable(self, address, data): if self.ramSize > 0: self.ramEnable = ((data & 0x0A) == 0x0A) - def writeROMBank(self, address, data): + def write_rom_bank(self, address, data): if data == 0: data = 1 self.romBank = ((data & 0x7F) << 14) & self.romSize - def writeRAMBank(self, address, data): - if (data >= 0x00 and data <= 0x03): + def write_ram_bank(self, address, data): + if data >= 0x00 and data <= 0x03: self.ramBank = (data << 13) & self.ramSize else: self.ramBank = -1 self.clockRegister = data - def writeClockLatch(self, address, data): - if (self.clockLatch == 0 and data == 1): + def write_clock_latch(self, address, data): + if self.clockLatch == 0 and data == 1: self.latchClock() - if (data == 0 or data == 1): + if data == 0 or data == 1: self.clockLatch = data - def writeClockData(self, address, data): - if (self.ramBank >= 0): + def write_clock_data(self, address, data): + if self.ramBank >= 0: self.ram[self.ramBank + (address & 0x1FFF)] = data else: self.updateClock() - if (self.clockRegister == 0x08): + if self.clockRegister == 0x08: self.clockSeconds = data - if (self.clockRegister == 0x09): + if self.clockRegister == 0x09: self.clockMinutes = data - if (self.clockRegister == 0x0A): + if self.clockRegister == 0x0A: self.clockHours = data - if (self.clockRegister == 0x0B): + if self.clockRegister == 0x0B: self.clockDays = data - if (self.clockRegister == 0x0C): + if self.clockRegister == 0x0C: self.clockControl = (self.clockControl & 0x80) | data - def latchClock(self): + def latch_clock(self): self.updateClock() self.clockLSeconds = self.clockSeconds self.clockLMinutes = self.clockMinutes @@ -501,30 +499,30 @@ self.clockLControl = (self.clockControl & 0xFE) | ((self.clockDays >> 8) & 0x01) - def updateClock(): - now = self.clock.getTime() - if ((self.clockControl & 0x40) == 0): + def update_clock(): + now = self.clock.get_time() + if (self.clockControl & 0x40) == 0: elapsed = now - self.clockTime - while (elapsed >= 246060): + while elapsed >= 246060: elapsed -= 246060 self.clockDays+=1 - while (elapsed >= 6060): + while elapsed >= 6060: elapsed -= 6060 self.clockHours+=1 - while (elapsed >= 60): + while elapsed >= 60: elapsed -= 60 self.clockMinutes+=1 self.clockSeconds += elapsed - while (self.clockSeconds >= 60): + while self.clockSeconds >= 60: self.clockSeconds -= 60 self.clockMinutes+=1 - while (self.clockMinutes >= 60): + while self.clockMinutes >= 60: self.clockMinutes -= 60 self.clockHours+=1 - while (self.clockHours >= 24): + while self.clockHours >= 24: self.clockHours -= 24 self.clockDays+=1 - while (self.clockDays >= 512): + while self.clockDays >= 512: self.clockDays -= 512 self.clockControl |= 0x80 self.clockTime = now @@ -555,23 +553,23 @@ def write(self, address, data): - if (address <= 0x1FFF): # 0000-1FFF + if address <= write_ram_enable: # 0000-1FFF self.writeRAMEnable(address, data) - elif (address <= 0x2FFF): # 2000-2FFF + elif address <= 0x2FFF: # 2000-2FFF self.romBank = ((self.romBank & (0x01 << 22)) + ((data & 0xFF) << 14)) & self.romSize - elif (address <= 0x3FFF): # 3000-3FFF + elif address <= 0x3FFF: # 3000-3FFF self.romBank = ((self.romBank & (0xFF << 14)) + ((data & 0x01) << 22)) & self.romSize - elif (address <= 0x4FFF): # 4000-4FFF - self.writeRAMBank(address, data) - elif (address >= 0xA000 and address <= 0xBFFF and self.ramEnable): # A000-BFFF + elif address <= 0x4FFF: # 4000-4FFF + self.write_ram_bank(address, data) + elif address >= 0xA000 and address <= 0xBFFF and self.ramEnable: # A000-BFFF self.ram[self.ramBank + (address & 0x1FFF)] = data - def writeRAMEnable(self, address, data): - if (self.ramSize > 0): + def write_ram_enable(self, address, data): + if self.ramSize > 0: self.ramEnable = ((data & 0x0A) == 0x0A) - def writeRAMBank(self, address, data): - if (self.rumble): + def write_ram_bank(self, address, data): + if self.rumble: self.ramBank = ((data & 0x07) << 13) & self.ramSize else: self.ramBank = ((data & 0x0F) << 13) & self.ramSize @@ -612,8 +610,8 @@ self.clockShift = 0 self.clockTime = 0 - self.setROM(rom) - self.setRAM(ram) + self.set_rom(rom) + self.set_ram(ram) self.ramFlag = 0 self.ramValue = 0 MBC.__init__(self, rom, ram, clockDriver) @@ -625,11 +623,11 @@ self.ramValue = 0 self.clockRegister = 0 self.clockShift = 0 - self.clockTime = self.clock.getTime() + self.clockTime = self.clock.get_time() def read(self, address): - if (address >= 0xA000 and address <= 0xBFFF):# A000-BFFF + if address >= 0xA000 and address <= 0xBFFF:# A000-BFFF if (self.ramFlag == 0x0C): return self.ramValue elif (self.ramFlag == 0x0D): @@ -641,54 +639,54 @@ super.read(address) def write(self, address, data): - if (address <= 0x1FFF): # 0000-1FFF + if address <= 0x1FFF: # 0000-1FFF self.ramFlag = data - elif (address <= 0x3FFF):# 2000-3FFF + elif address <= 0x3FFF:# 2000-3FFF self.writeROMBank(address, data) - elif (address <= 0x5FFF): # 4000-5FFF + elif address <= 0x5FFF: # 4000-5FFF self.ramBank = ((data & 0x0F) << 13) & self.ramSize - elif (address >= 0xA000 and address <= 0xBFFF): # A000-BFFF + elif address >= 0xA000 and address <= 0xBFFF: # A000-BFFF self.writeRAMFlag(address, data) - def writeROMBank(self, address, data): - if ((data & 0x7F) == 0): + def write_rom_bank(self, address, data): + if (data & 0x7F) == 0: data = 1 self.romBank = ((data & 0x7F) << 14) & self.romSize - def writeRAMFlag(self, address, data): - if (self.ramFlag == 0x0B): + def write_ram_flag(self, address, data): + if self.ramFlag == 0x0B: self.writeWithRamFlag0x0B(address, data) elif (self.ramFlag >= 0x0C and self.ramFlag <= 0x0E): pass - elif (self.ramFlag == 0x0A and self.ramSize > 0): + elif self.ramFlag == 0x0A and self.ramSize > 0: self.ram[self.ramBank + (address & 0x1FFF)] = data - def writeWithRamFlag0x0B(self, address, data): - if ((data & 0xF0) == 0x10): - self.writeRAMValueClockShift(address, data) - elif ((data & 0xF0) == 0x30): - self.writeClockRegisterClockShift(address, data) - elif ((data & 0xF0) == 0x40): - self.writeClockShift(address, data) - elif ((data & 0xF0) == 0x50): + def write_with_ram_flag_0x0B(self, address, data): + if (data & 0xF0) == 0x10: + self.write_ram_value_clock_shift(address, data) + elif (data & 0xF0) == 0x30: + self.write_clock_register_clock_shift(address, data) + elif (data & 0xF0) == 0x40: + self.write_clock_shift(address, data) + elif (data & 0xF0) == 0x50: pass - elif ((data & 0xF0) == 0x60): + elif (data & 0xF0) == 0x60: self.ramValue = 0x01 - def writeRAMValueClockShift(self, address, data): + def write_ram_value_clock_shift(self, address, data): if self.clockShift > 24: return self.ramValue = (self.clockRegister >> self.clockShift) & 0x0F self.clockShift += 4 - def writeClockRegisterClockShift(self, address, data): + def write_clock_register_clock_shift(self, address, data): if self.clockShift > 24: return self.clockRegister &= ~(0x0F << self.clockShift) self.clockRegister |= ((data & 0x0F) << self.clockShift) self.clockShift += 4 - def writeClocckShift(self, address, data): + def write_clock_shift(self, address, data): switch = data & 0x0F self.updateClock() if switch == 0: @@ -698,24 +696,24 @@ elif switch == 7: self.clockShift = 0 - def updateClock(self): + def update_clock(self): now = self.clock.getTime() elapsed = now - self.clockTime # years (4 bits) - while (elapsed >= 365246060): + while elapsed >= 365246060: self.clockRegister += 1 << 24 elapsed -= 365246060 # days (12 bits) - while (elapsed >= 246060): + while elapsed >= 246060: self.clockRegister += 1 << 12 elapsed -= 246060 # minutes (12 bits) - while (elapsed >= 60): + while elapsed >= 60: self.clockRegister += 1 elapsed -= 60 - if ((self.clockRegister & 0x0000FFF) >= 2460): + if (self.clockRegister & 0x0000FFF) >= 2460: self.clockRegister += (1 << 12) - 2460 - if ((self.clockRegister & 0x0FFF000) >= (365 << 12)): + if (self.clockRegister & 0x0FFF000) >= (365 << 12): self.clockRegister += (1 << 24) - (365 << 12) self.clockTime = now - elapsed Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py Thu May 8 13:54:14 2008 @@ -26,7 +26,7 @@ def sub(self, value, useCycles=True): self.set(self.get(useCycles)-value, useCycles) -# ------------------------------------------------------------------------------ +#------------------------------------------------------------------------------ class DoubleRegister(object): @@ -44,30 +44,30 @@ def set(self, hi=0, lo=None, useCycles=True): if lo is None: - self.setHi(hi >> 8, useCycles) - self.setLo(hi & 0xFF, useCycles) + self.set_hi(hi >> 8, useCycles) + self.set_lo(hi & 0xFF, useCycles) if useCycles: self.cpu.cycles += 1 else: - self.setHi(hi, useCycles) - self.setLo(lo, useCycles) + self.set_hi(hi, useCycles) + self.set_lo(lo, useCycles) def reset(self): self.set(self.resetValue, useCycles=False) - def setHi(self, hi=0, useCycles=True): + def set_hi(self, hi=0, useCycles=True): self.hi.set(hi, useCycles) - def setLo(self, lo=0, useCycles=True): + def set_lo(self, lo=0, useCycles=True): self.lo.set(lo, useCycles) def get(self, useCycles=True): return (self.hi.get(useCycles)<<8) + self.lo.get(useCycles) - def getHi(self, useCycles=True): + def get_hi(self, useCycles=True): return self.hi.get(useCycles) - def getLo(self, useCycles=True): + def get_lo(self, useCycles=True): return self.lo.get(useCycles) def inc(self, useCycles=True): @@ -144,24 +144,24 @@ if useCycles: self.cpu.cycles -= 1 - def zFlagCompare(self, a, reset=False): + def z_flag_compare(self, a, reset=False): if (reset): self.reset() if isinstance(a, (Register)): a = a.get() self.zFlag = ((a & 0xFF) == 0) - def cFlagAdd(self, s, compareAnd=0x01, reset=False): + def c_flag_add(self, s, compare_and=0x01, reset=False): if (reset): self.reset() - if (s & compareAnd) != 0: + if (s & compare_and) != 0: self.cFlag = True - def hFlagCompare(self, a, b): + def h_flag_compare(self, a, b): if (a & 0x0F) < (b & 0x0F): self.hFlag = True - def cFlagCompare(self, a, b): + def c_flag_compare(self, a, b): if a < b: self.cFlag = True @@ -179,11 +179,11 @@ self.ime = False self.halted = False self.cycles = 0 - self.iniRegisters() + self.ini_registers() self.rom = [] self.reset() - def iniRegisters(self): + def ini_registers(self): self.b = Register(self) self.c = Register(self) self.bc = DoubleRegister(self, self.b, self.c, constants.RESET_BC) @@ -206,14 +206,14 @@ def reset(self): - self.resetRegisters() + self.reset_registers() self.f.reset() self.f.zFlag = True self.ime = False self.halted = False self.cycles = 0 - def resetRegisters(self): + def reset_registers(self): self.a.reset() self.f.reset() self.bc.reset() @@ -222,49 +222,49 @@ self.sp.reset() self.pc.reset() - def getAF(self): + def get_af(self): return self.af - def getA(self): + def get_a(self): return self.a - def getF(self): + def get_f(self): return self.f - def getBC(self): + def get_bc(self): return self.bc - def getB(self): + def get_b(self): return self.b - def getC(self): + def get_c(self): return self.c - def getDE(self): + def get_de(self): return self.de - def getD(self): + def get_d(self): return self.d - def getE(self): + def get_e(self): return self.e - def getHL(self): + def get_hl(self): return self.hl - def getHLi(self): + def get_hli(self): return self.hli - def getH(self): + def get_h(self): return self.h - def getL(self): + def get_l(self): return self.l - def getSP(self): + def get_sp(self): return self.sp - def getIF(self): + def get_if(self): val = 0x00 if self.ime: val = 0x01 @@ -272,71 +272,69 @@ val += 0x80 return val - def isZ(self): + def is_z(self): """ zero flag""" return self.f.zFlag - def isC(self): + def is_c(self): """ carry flag, true if the result did not fit in the register""" return self.f.cFlag - def isH(self): + def is_h(self): """ half carry, carry from bit 3 to 4""" return self.f.hFlag - def isN(self): + def is_n(self): """ subtract flag, true if the last operation was a subtraction""" return self.f.nFlag def isS(self): return self.f.sFlag - def isP(self): + def is_p(self): return self.f.pFlag - def isNotZ(self): - return not self.isZ() + def is_not_z(self): + return not self.is_z() - def isNotC(self): - return not self.isC() + def is_not_c(self): + return not self.is_c() - def isNotH(self): - return not self.isH() + def is_not_h(self): + return not self.is_h() - def isNotN(self): - return not self.isN() + def is_not_n(self): + return not self.is_n() - def setROM(self, banks): - - # Flags ............................................ + def set_rom(self, banks): self.rom = banks def emulate(self, ticks): self.cycles += ticks - self.handlePendingInterrupt() + self.handle_pending_interrupt() while self.cycles > 0: self.execute(self.fetch()) - def handlePendingInterrupt(self): + def handle_pending_interrupt(self): # Interrupts if self.halted: - if self.interrupt.isPending(): + if self.interrupt.is_pending(): self.halted = False self.cycles -= 4 elif (self.cycles > 0): self.cycles = 0 - if self.ime and self.interrupt.isPending(): - self.lowerPendingInterrupt() + if self.ime and self.interrupt.is_pending(): + self.lower_pending_interrupt() - def lowerPendingInterrupt(self): + def lower_pending_interrupt(self): for flag in self.interrupt.interruptFlags: - if flag.isPending(): + if flag.is_pending(): self.ime = False self.call(flag.callCode, useCycles=False) - flag.setPending(False) + flag.set_pending(False) return - def fetchExecute(self): + def fetch_execute(self): # Execution FETCH_EXECUTE_OP_CODES[self.fetch()](self) @@ -366,23 +364,23 @@ self.pc.inc(useCycles) # 2 cycles return data - def fetchDoubleAddress(self): + def fetch_double_address(self): lo = self.fetch() # 1 cycle hi = self.fetch() # 1 cycle return (hi << 8) + lo - def fetchDoubleRegister(self, register): - self.popDoubleRegister(CPU.fetch, register) + def fetch_double_register(self, register): + self.pop_double_register(CPU.fetch, register) def push(self, data, useCycles=True): # Stack, 2 cycles self.sp.dec(useCycles) # 2 cycles self.memory.write(self.sp.get(useCycles), data) - def pushDoubleRegister(self, register, useCycles=True): + def push_double_register(self, register, useCycles=True): # PUSH rr 4 cycles - self.push(register.getHi(), useCycles) # 2 cycles - self.push(register.getLo(), useCycles) # 2 cycles + self.push(register.get_hi(), useCycles) # 2 cycles + self.push(register.get_lo(), useCycles) # 2 cycles def pop(self): # 1 cycle @@ -391,7 +389,7 @@ self.cycles += 1 return data - def popDoubleRegister(self, getter, register=None): + def pop_double_register(self, getter, register=None): # 3 cycles if register == None: register = getter @@ -403,8 +401,8 @@ def call(self, address, useCycles=True): # 4 cycles - self.push(self.pc.getHi(useCycles), useCycles) # 2 cycles - self.push(self.pc.getLo(useCycles), useCycles) # 2 cycles + self.push(self.pc.get_hi(useCycles), useCycles) # 2 cycles + self.push(self.pc.get_lo(useCycles), useCycles) # 2 cycles self.pc.set(address, useCycles=useCycles) # 1 cycle if useCycles: self.cycles += 1 @@ -413,103 +411,103 @@ # 1 cycle setter(getter()) # 1 cycle - def loadFetchRegister(self, register): + def load_fetch_register(self, register): self.ld(self.fetch, register.set) - def storeHlInPC(self): + def store_hl_in_pc(self): # LD PC,HL, 1 cycle self.ld(self.hl.get, self.pc.set) - def fetchLoad(self, getter, setter): + def fetch_load(self, getter, setter): self.ld(self.fetch, setter) - def addA(self, getter, setter=None): + def add_a(self, getter, setter=None): # ALU, 1 cycle added = (self.a.get() + getter()) & 0xFF - self.f.zFlagCompare(added, reset=True) - self.f.hFlagCompare(added, self.a.get()) - self.f.cFlagCompare(added, self.a.get()) + self.f.z_flag_compare(added, reset=True) + self.f.h_flag_compare(added, self.a.get()) + self.f.c_flag_compare(added, self.a.get()) self.a.set(added) # 1 cycle - def addHL(self, register): + def add_hl(self, register): # 2 cycles a=1 added = (self.hl.get() + register.get()) & 0xFFFF # 1 cycle self.f.reset(keepZ=True) - self.f.hFlagCompare((added >> 8), self.hl.get()) - self.f.cFlagCompare(added, self.hl.get()) + self.f.h_flag_compare((added >> 8), self.hl.get()) + self.f.c_flag_compare(added, self.hl.get()) self.hl.set(added) self.cycles -= 1 - def addWithCarry(self, getter, setter=None): + def add_with_carry(self, getter, setter=None): # 1 cycle data = getter() s = self.a.get() + data if self.f.cFlag: s +=1 - self.carryFlagFinish(s,data) + self.carry_flag_finish(s,data) - def subtractWithCarry(self, getter, setter=None): + def subtract_with_carry(self, getter, setter=None): # 1 cycle data = getter() s = self.a.get() - data if self.f.cFlag: s -= 1 - self.carryFlagFinish(s, data) + self.carry_flag_finish(s, data) self.f.nFlag = True - def carryFlagFinish(self, s, data): + def carry_flag_finish(self, s, data): self.f.reset() # set the hflag if the 0x10 bit was affected if ((s ^ self.a.get() ^ data) & 0x10) != 0: self.f.hFlag = True if s >= 0x100: self.f.cFlag= True - self.f.zFlagCompare(s) + self.f.z_flag_compare(s) self.a.set(s) # 1 cycle - def subtractA(self, getter, setter=None): + def subtract_a(self, getter, setter=None): # 1 cycle - self.compareA(getter, setter) # 1 cycle + self.compare_a(getter, setter) # 1 cycle self.a.sub(getter(useCycles=False), False) - def fetchSubtractA(self): + def fetch_subtract_a(self): data = self.fetch() - self.subtractA(lambda useCycles=False: data) + self.subtract_a(lambda useCycles=False: data) - def compareA(self, getter, setter=None): + def compare_a(self, getter, setter=None): # 1 cycle s = (self.a.get() - getter()) & 0xFF self.f.reset() self.f.nFlag = True - self.f.zFlagCompare(s) - self.hcFlagFinish(s) + self.f.z_flag_compare(s) + self.hc_flag_finish(s) self.cycles -= 1 - def hcFlagFinish(self, data): + def hc_flag_finish(self, data): if data > self.a.get(): self.f.cFlag = True - self.f.hFlagCompare(self.a.get(), data) + self.f.h_flag_compare(self.a.get(), data) def AND(self, getter, setter=None): # 1 cycle self.a.set(self.a.get() & getter()) # 1 cycle - self.f.zFlagCompare(self.a.get(), reset=True) + self.f.z_flag_compare(self.a.get(), reset=True) def XOR(self, getter, setter=None): # 1 cycle self.a.set( self.a.get() ^ getter()) # 1 cycle - self.f.zFlagCompare(self.a.get(), reset=True) + self.f.z_flag_compare(self.a.get(), reset=True) def OR(self, getter, setter=None): # 1 cycle self.a.set(self.a.get() | getter()) # 1 cycle - self.f.zFlagCompare(self.a.get(), reset=True) + self.f.z_flag_compare(self.a.get(), reset=True) - def incDoubleRegister(self, doubleRegister): + def inc_double_register(self, doubleRegister): doubleRegister.inc() - def decDoubleRegister(self, doubleRegister): + def dec_double_register(self, doubleRegister): doubleRegister.dec() def inc(self, getter, setter): @@ -525,85 +523,85 @@ def decIncFlagFinish(self, data, setter, compare): self.f.reset(keepC=True) - self.f.zFlagCompare(data) + self.f.z_flag_compare(data) if (data & 0x0F) == compare: self.f.hFlag = True setter(data) # 1 cycle - def rotateLeftCircular(self, getter, setter): + def rotate_left_circular(self, getter, setter): # RLC 1 cycle data = getter() s = (data << 1) + (data >> 7) - self.flagsAndSetterFinish(s, setter, 0x80) + self.flags_and_setter_finish(s, setter, 0x80) #self.cycles -= 1 - def rotateLeftCircularA(self): - # RLCA rotateLeftCircularA 1 cycle - self.rotateLeftCircular(self.a.get, self.a.set) + def rotate_left_circular_a(self): + # RLCA rotate_left_circular_a 1 cycle + self.rotate_left_circular(self.a.get, self.a.set) - def rotateLeft(self, getter, setter): + def rotate_left(self, getter, setter): # 1 cycle s = (getter() << 1) & 0xFF if self.f.cFlag: s += 0x01 - self.flagsAndSetterFinish(s, setter, 0x80) # 1 cycle + self.flags_and_setter_finish(s, setter, 0x80) # 1 cycle - def rotateLeftA(self): + def rotate_left_a(self): # RLA 1 cycle - self.rotateLeft(self.a.get, self.a.set) + self.rotate_left(self.a.get, self.a.set) - def rotateRightCircular(self, getter, setter): + def rotate_right_circular(self, getter, setter): data = getter() # RRC 1 cycle s = (data >> 1) + ((data & 0x01) << 7) - self.flagsAndSetterFinish(s, setter) # 1 cycle + self.flags_and_setter_finish(s, setter) # 1 cycle - def rotateRightCircularA(self): + def rotate_right_circular_a(self): # RRCA 1 cycle - self.rotateRightCircular(self.a.get, self.a.set) + self.rotate_right_circular(self.a.get, self.a.set) - def rotateRight(self, getter, setter): + def rotate_right(self, getter, setter): # 1 cycle s = (getter() >> 1) if self.f.cFlag: s += 0x08 - self.flagsAndSetterFinish(s, setter) # 1 cycle + self.flags_and_setter_finish(s, setter) # 1 cycle - def rotateRightA(self): + def rotate_right_a(self): # RRA 1 cycle - self.rotateRight(self.a.get, self.a.set) + self.rotate_right(self.a.get, self.a.set) - def shiftLeftArithmetic(self, getter, setter): + def shift_left_arithmetic(self, getter, setter): # 2 cycles s = (getter() << 1) & 0xFF - self.flagsAndSetterFinish(s, setter, 0x80) # 1 cycle + self.flags_and_setter_finish(s, setter, 0x80) # 1 cycle - def shiftRightArithmetic(self, getter, setter): + def shift_right_arithmetic(self, getter, setter): data = getter() # 1 cycle s = (data >> 1) + (data & 0x80) - self.flagsAndSetterFinish(s, setter) # 1 cycle + self.flags_and_setter_finish(s, setter) # 1 cycle - def shiftWordRightLogical(self, getter, setter): + def shift_word_right_logical(self, getter, setter): # 2 cycles s = (getter() >> 1) - self.flagsAndSetterFinish(s, setter) # 2 cycles + self.flags_and_setter_finish(s, setter) # 2 cycles - def flagsAndSetterFinish(self, s, setter, compareAnd=0x01): + def flags_and_setter_finish(self, s, setter, compare_and=0x01): # 2 cycles s &= 0xFF - self.f.zFlagCompare(s, reset=True) - self.f.cFlagAdd(s, compareAnd) + self.f.z_flag_compare(s, reset=True) + self.f.c_flag_add(s, compare_and) setter(s) # 1 cycle def swap(self, getter, setter): data = getter() # 1 cycle s = ((data << 4) + (data >> 4)) & 0xFF - self.f.zFlagCompare(s, reset=True) + self.f.z_flag_compare(s, reset=True) setter(s) - def testBit(self, getter, setter, n): + def test_bit(self, getter, setter, n): # 2 cycles self.f.reset(keepC=True) self.f.hFlag = True @@ -612,103 +610,103 @@ self.f.zFlag = True self.cycles -= 1 - def setBit(self, getter, setter, n): + def set_bit(self, getter, setter, n): # 1 cycle setter(getter() | (1 << n)) # 1 cycle - def resetBit(self, getter, setter, n): + def reset_bit(self, getter, setter, n): # 1 cycle setter(getter() & (~(1 << n))) # 1 cycle - def storeFetchedMemoryInA(self): + def store_fetched_memory_in_a(self): # LD A,(nnnn), 4 cycles - self.a.set(self.read(self.fetchDoubleAddress())) # 1+1 + 2 cycles + self.a.set(self.read(self.fetch_double_address())) # 1+1 + 2 cycles - def writeAAtBCAddress(self): + def write_a_at_bc_address(self): # 2 cycles self.write(self.bc.get(), self.a.get()) - def writeAAtDEAddress(self): + def write_a_at_de_address(self): self.write(self.de.get(), self.a.get()) - def storeMemoryAtBCInA(self): + def store_memory_at_bc_in_a(self): self.a.set(self.read(self.bc.get())) - def storeMemoryAtDEInA(self): + def store_memory_at_de_in_a(self): self.a.set(self.read(self.de.get())) def ld_dbRegisteri_A(self, register): # LD (rr),A 2 cycles self.write(register.get(), self.a.get()) # 2 cycles - def load_mem_SP(self): + def load_mem_sp(self): # LD (nnnn),SP 5 cycles - address = self.fetchDoubleAddress() # 2 cycles - self.write(address, self.sp.getLo()) # 2 cycles - self.write((address + 1), self.sp.getHi()) # 2 cycles + address = self.fetch_double_address() # 2 cycles + self.write(address, self.sp.get_lo()) # 2 cycles + self.write((address + 1), self.sp.get_hi()) # 2 cycles self.cycles += 1 - def storeAAtFetchedAddress(self): + def store_a_at_fetched_address(self): # LD (nnnn),A 4 cycles - self.write(self.fetchDoubleAddress(), self.a.get()) # 2 cycles + self.write(self.fetch_double_address(), self.a.get()) # 2 cycles - def storeMemoryAtExpandedFetchAddressInA(self): + def store_memory_at_axpanded_fetch_address_in_a(self): # LDH A,(nn) 3 cycles self.a.set(self.read(0xFF00 + self.fetch())) # 1+1+1 cycles - def storeExpandedCinA(self): + def store_expanded_c_in_a(self): # LDH A,(C) 2 cycles - self.a.set(self.read(0xFF00 + self.bc.getLo())) # 1+2 cycles + self.a.set(self.read(0xFF00 + self.bc.get_lo())) # 1+2 cycles - def loadAndIncrement_A_HLi(self): + def load_and_increment_a_hli(self): # loadAndIncrement A,(HL) 2 cycles self.a.set(self.read(self.hl.get())) # 2 cycles self.hl.inc()# 2 cycles self.cycles += 2 - def loadAndDecrement_A_HLi(self): + def load_and_decrement_a_hli(self): # loadAndDecrement A,(HL) 2 cycles self.a.set(self.read(self.hl.get())) # 2 cycles self.hl.dec() # 2 cycles self.cycles += 2 - def writeAatExpandedFetchAddress(self): + def write_a_at_expanded_fetch_address(self): # LDH (nn),A 3 cycles self.write(0xFF00 + self.fetch(), self.a.get()) # 2 + 1 cycles - def writeAAtExpandedCAddress(self): + def write_a_at_expaded_c_address(self): # LDH (C),A 2 cycles - self.write(0xFF00 + self.bc.getLo(), self.a.get()) # 2 cycles + self.write(0xFF00 + self.bc.get_lo(), self.a.get()) # 2 cycles - def loadAndIncrement_HLi_A(self): + def load_and_increment_hli_a(self): # loadAndIncrement (HL),A 2 cycles self.write(self.hl.get(), self.a.get()) # 2 cycles self.hl.inc() # 2 cycles self.cycles += 2 - def loadAndDecrement_HLi_A(self): + def load_and_decrement_hli_a(self): # loadAndDecrement (HL),A 2 cycles self.write(self.hl.get(), self.a.get()) # 2 cycles self.hl.dec() # 2 cycles self.cycles += 2 - def storeHlInSp(self): + def store_hl_in_sp(self): # LD SP,HL 2 cycles self.sp.set(self.hl.get()) # 1 cycle self.cycles -= 1 - def complementA(self): + def complement_a(self): # CPA self.a.set(self.a.get() ^ 0xFF) self.f.nFlag = True self.f.hFlag = True - def decimalAdjustAccumulator(self): + def decimal_adjust_accumulator(self): # DAA 1 cycle delta = 0 - if self.isH(): + if self.is_h(): delta |= 0x06 - if self.isC(): + if self.is_c(): delta |= 0x60 if (self.a.get() & 0x0F) > 0x09: delta |= 0x06 @@ -716,34 +714,34 @@ delta |= 0x60 if (self.a.get() & 0xF0) > 0x90: delta |= 0x60 - if not self.isN(): + if not self.is_n(): self.a.set((self.a.get() + delta) & 0xFF) # 1 cycle else: self.a.set((self.a.get() - delta) & 0xFF) # 1 cycle self.f.reset(keepN=True) if delta >= 0x60: self.f.cFlag = True - self.f.zFlagCompare(self.a.get()) + self.f.z_flag_compare(self.a.get()) - def incDoubleRegister(self, register): + def inc_double_register(self, register): # INC rr register.inc() - def decDoubleRegister(self, register): + def dec_double_register(self, register): # DEC rr register.dec() - def incrementSPByFetch(self): + def increment_sp_by_fetch(self): # ADD SP,nn 4 cycles - self.sp.set(self.getFetchAddedSP()) # 1+1 cycle + self.sp.set(self.get_fetchadded_sp()) # 1+1 cycle self.cycles -= 2 - def storeFetchAddedSPInHL(self): + def store_fetch_added_sp_in_hl(self): # LD HL,SP+nn 3 cycles - self.hl.set(self.getFetchAddedSP()) # 1+1 cycle + self.hl.set(self.get_fetchadded_sp()) # 1+1 cycle self.cycles -= 1 - def getFetchAddedSP(self): + def get_fetchadded_sp(self): # 1 cycle offset = self.fetch() # 1 cycle s = (self.sp.get() + offset) & 0xFFFF @@ -760,12 +758,12 @@ self.f.hFlag = True return s - def complementCarryFlag(self): + def complement_carry_flag(self): # CCF/SCF self.f.reset(keepZ=True, keepC=True) self.f.cFlag = not self.f.cFlag - def setCarryFlag(self): + def set_carry_flag(self): self.f.reset(keepZ=True) self.f.cFlag = True @@ -773,38 +771,38 @@ # NOP 1 cycle self.cycles -= 1 - def unconditionalJump(self): + def unconditional_jump(self): # JP nnnn, 4 cycles - self.pc.set(self.fetchDoubleAddress()) # 1+2 cycles + self.pc.set(self.fetch_double_address()) # 1+2 cycles self.cycles -= 1 - def conditionalJump(self, cc): + def conditional_jump(self, cc): # JP cc,nnnn 3,4 cycles if cc: - self.unconditionalJump() # 4 cycles + self.unconditional_jump() # 4 cycles else: self.pc.add(2) # 3 cycles - def relativeUnconditionalJump(self): + def relative_unconditional_jump(self): # JR +nn, 3 cycles self.pc.add(self.fetch()) # 3 + 1 cycles self.cycles += 1 - def relativeConditionalJump(self, cc): + def relative_conditional_jump(self, cc): # JR cc,+nn, 2,3 cycles if cc: - self.relativeUnconditionalJump() # 3 cycles + self.relative_unconditional_jump() # 3 cycles else: self.pc.inc() # 2 cycles - def unconditionalCall(self): + def unconditional_call(self): # CALL nnnn, 6 cycles - self.call(self.fetchDoubleAddress()) # 4+2 cycles + self.call(self.fetch_double_address()) # 4+2 cycles - def conditionalCall(self, cc): + def conditional_call(self, cc): # CALL cc,nnnn, 3,6 cycles if cc: - self.unconditionalCall() # 6 cycles + self.unconditional_call() # 6 cycles else: self.pc.add(2) # 3 cycles @@ -814,7 +812,7 @@ hi = self.pop() # 1 cycle self.pc.set(hi, lo) # 2 cycles - def conditionalReturn(self, cc): + def conditional_return(self, cc): # RET cc 2,5 cycles if cc: self.ret() # 4 cycles @@ -823,34 +821,34 @@ else: self.cycles -= 2 - def returnFormInterrupt(self): + def return_form_interrupt(self): # RETI 4 cycles self.ret() # 4 cycles - self.enableInterrupts() # 1 cycle + others + self.enable_interrups() # 1 cycle + others self.cycles += 1 def restart(self, nn): # RST nn 4 cycles self.call(nn) # 4 cycles - def disableInterrupts(self): + def disable_interrups(self): # DI/EI 1 cycle self.ime = False self.cycles -= 1 - def enableInterrupts(self): + def enable_interrups(self): # 1 cycle self.ime = True self.execute(self.fetch()) # 1 - self.handlePendingInterrupt() + self.handle_pending_interrupt() def halt(self): # HALT/STOP self.halted = True # emulate bug when interrupts are pending - if (not self.ime and self.interrupt.isPending()): + if (not self.ime and self.interrupt.is_pending()): self.execute(self.memory.read(self.pc.get())) - self.handlePendingInterrupt() + self.handle_pending_interrupt() def stop(self): # 0 cycles @@ -861,7 +859,7 @@ # OPCODE LOOKUP TABLE GENERATION ----------------------------------------------- -GROUPED_REGISTERS = (CPU.getB, CPU.getC, CPU.getD, CPU.getE, CPU.getH, CPU.getL, CPU.getHLi, CPU.getA) +GROUPED_REGISTERS = (CPU.get_b, CPU.get_c, CPU.get_d, CPU.get_e, CPU.get_h, CPU.get_l, CPU.get_hli, CPU.get_a) def create_group_op_codes(table): opCodes =[] @@ -900,7 +898,7 @@ opCode = 0x40 for storeRegister in GROUPED_REGISTERS: for loadRegister in GROUPED_REGISTERS: - if loadRegister != CPU.getHLi or storeRegister != CPU.getHLi: + if loadRegister != CPU.get_hli or storeRegister != CPU.get_hli: opCodes.append((opCode, load_group_lambda(storeRegister, loadRegister))) opCode += 1 return opCodes @@ -944,51 +942,51 @@ FIRST_ORDER_OP_CODES = [ (0x00, CPU.nop), - (0x08, CPU.load_mem_SP), + (0x08, CPU.load_mem_sp), (0x10, CPU.stop), - (0x18, CPU.relativeUnconditionalJump), - (0x02, CPU.writeAAtBCAddress), - (0x12, CPU.writeAAtDEAddress), - (0x22, CPU.loadAndIncrement_HLi_A), - (0x32, CPU.loadAndDecrement_HLi_A), - (0x0A, CPU.storeMemoryAtBCInA), - (0x1A, CPU.storeMemoryAtDEInA), - (0x2A, CPU.loadAndIncrement_A_HLi), - (0x3A, CPU.loadAndDecrement_A_HLi), - (0x07, CPU.rotateLeftCircularA), - (0x0F, CPU.rotateRightCircularA), - (0x17, CPU.rotateLeftA), - (0x1F, CPU.rotateRightA), - (0x27, CPU.decimalAdjustAccumulator), - (0x2F, CPU.complementA), - (0x37, CPU.setCarryFlag), - (0x3F, CPU.complementCarryFlag), + (0x18, CPU.relative_unconditional_jump), + (0x02, CPU.write_a_at_bc_address), + (0x12, CPU.write_a_at_de_address), + (0x22, CPU.load_and_increment_hli_a), + (0x32, CPU.load_and_decrement_hli_a), + (0x0A, CPU.store_memory_at_bc_in_a), + (0x1A, CPU.store_memory_at_de_in_a), + (0x2A, CPU.load_and_increment_a_hli), + (0x3A, CPU.load_and_decrement_a_hli), + (0x07, CPU.rotate_left_circular_a), + (0x0F, CPU.rotate_right_circular_a), + (0x17, CPU.rotate_left_a), + (0x1F, CPU.rotate_right_a), + (0x27, CPU.decimal_adjust_accumulator), + (0x2F, CPU.complement_a), + (0x37, CPU.set_carry_flag), + (0x3F, CPU.complement_carry_flag), (0x76, CPU.halt), - (0xF3, CPU.disableInterrupts), - (0xFB, CPU.enableInterrupts), - (0xE2, CPU.writeAAtExpandedCAddress), - (0xEA, CPU.storeAAtFetchedAddress), - (0xF2, CPU.storeExpandedCinA), - (0xFA, CPU.storeFetchedMemoryInA), - (0xC3, CPU.unconditionalJump), + (0xF3, CPU.disable_interrups), + (0xFB, CPU.enable_interrups), + (0xE2, CPU.write_a_at_expaded_c_address), + (0xEA, CPU.store_a_at_fetched_address), + (0xF2, CPU.store_expanded_c_in_a), + (0xFA, CPU.store_fetched_memory_in_a), + (0xC3, CPU.unconditional_jump), (0xC9, CPU.ret), - (0xD9, CPU.returnFormInterrupt), - (0xE9, CPU.storeHlInPC), - (0xF9, CPU.storeHlInSp), - (0xE0, CPU.writeAatExpandedFetchAddress), - (0xE8, CPU.incrementSPByFetch), - (0xF0, CPU.storeMemoryAtExpandedFetchAddressInA), - (0xF8, CPU.storeFetchAddedSPInHL), - (0xCB, CPU.fetchExecute), - (0xCD, CPU.unconditionalCall), - (0xC6, lambda s: CPU.addA(s, s.fetch)), - (0xCE, lambda s: CPU.addWithCarry(s, s.fetch)), - (0xD6, CPU.fetchSubtractA), - (0xDE, lambda s: CPU.subtractWithCarry(s, s.fetch)), + (0xD9, CPU.return_form_interrupt), + (0xE9, CPU.store_hl_in_pc), + (0xF9, CPU.store_hl_in_sp), + (0xE0, CPU.write_a_at_expanded_fetch_address), + (0xE8, CPU.increment_sp_by_fetch), + (0xF0, CPU.store_memory_at_axpanded_fetch_address_in_a), + (0xF8, CPU.store_fetch_added_sp_in_hl), + (0xCB, CPU.fetch_execute), + (0xCD, CPU.unconditional_call), + (0xC6, lambda s: CPU.add_a(s, s.fetch)), + (0xCE, lambda s: CPU.add_with_carry(s, s.fetch)), + (0xD6, CPU.fetch_subtract_a), + (0xDE, lambda s: CPU.subtract_with_carry(s, s.fetch)), (0xE6, lambda s: CPU.AND(s, s.fetch)), (0xEE, lambda s: CPU.XOR(s, s.fetch)), (0xF6, lambda s: CPU.OR(s, s.fetch)), - (0xFE, lambda s: CPU.compareA(s, s.fetch)), + (0xFE, lambda s: CPU.compare_a(s, s.fetch)), (0xC7, lambda s: CPU.restart(s, 0x00)), (0xCF, lambda s: CPU.restart(s, 0x08)), (0xD7, lambda s: CPU.restart(s, 0x10)), @@ -1002,47 +1000,47 @@ REGISTER_GROUP_OP_CODES = [ (0x04, 0x08, CPU.inc), (0x05, 0x08, CPU.dec), - (0x06, 0x08, CPU.loadFetchRegister), - (0x80, 0x01, CPU.addA), - (0x88, 0x01, CPU.addWithCarry), - (0x90, 0x01, CPU.subtractA), - (0x98, 0x01, CPU.subtractWithCarry), + (0x06, 0x08, CPU.load_fetch_register), + (0x80, 0x01, CPU.add_a), + (0x88, 0x01, CPU.add_with_carry), + (0x90, 0x01, CPU.subtract_a), + (0x98, 0x01, CPU.subtract_with_carry), (0xA0, 0x01, CPU.AND), (0xA8, 0x01, CPU.XOR), (0xB0, 0x01, CPU.OR), - (0xB8, 0x01, CPU.compareA), - (0x06, 0x08, CPU.fetchLoad) + (0xB8, 0x01, CPU.compare_a), + (0x06, 0x08, CPU.fetch_load) ] -REGISTER_SET_A = [CPU.getBC, CPU.getDE, CPU.getHL, CPU.getSP] -REGISTER_SET_B = [CPU.getBC, CPU.getDE, CPU.getHL, CPU.getAF] -FLAG_REGISTER_SET = [CPU.isNotZ, CPU.isZ, CPU.isNotC, CPU.isC] +REGISTER_SET_A = [CPU.get_bc, CPU.get_de, CPU.get_hl, CPU.get_sp] +REGISTER_SET_B = [CPU.get_bc, CPU.get_de, CPU.get_hl, CPU.get_af] +FLAG_REGISTER_SET = [CPU.is_not_z, CPU.is_z, CPU.is_not_c, CPU.is_c] REGISTER_OP_CODES = [ - (0x01, 0x10, CPU.fetchDoubleRegister, REGISTER_SET_A), - (0x09, 0x10, CPU.addHL, REGISTER_SET_A), - (0x03, 0x10, CPU.incDoubleRegister, REGISTER_SET_A), - (0x0B, 0x10, CPU.decDoubleRegister, REGISTER_SET_A), - (0xC0, 0x08, CPU.conditionalReturn, FLAG_REGISTER_SET), - (0xC2, 0x08, CPU.conditionalJump, FLAG_REGISTER_SET), - (0xC4, 0x08, CPU.conditionalCall, FLAG_REGISTER_SET), - (0x20, 0x08, CPU.relativeConditionalJump, FLAG_REGISTER_SET), - (0xC1, 0x10, CPU.popDoubleRegister, REGISTER_SET_B), - (0xC5, 0x10, CPU.pushDoubleRegister, REGISTER_SET_B) + (0x01, 0x10, CPU.fetch_double_register, REGISTER_SET_A), + (0x09, 0x10, CPU.add_hl, REGISTER_SET_A), + (0x03, 0x10, CPU.inc_double_register, REGISTER_SET_A), + (0x0B, 0x10, CPU.dec_double_register, REGISTER_SET_A), + (0xC0, 0x08, CPU.conditional_return, FLAG_REGISTER_SET), + (0xC2, 0x08, CPU.conditional_jump, FLAG_REGISTER_SET), + (0xC4, 0x08, CPU.conditional_call, FLAG_REGISTER_SET), + (0x20, 0x08, CPU.relative_conditional_jump, FLAG_REGISTER_SET), + (0xC1, 0x10, CPU.pop_double_register, REGISTER_SET_B), + (0xC5, 0x10, CPU.push_double_register, REGISTER_SET_B) ] SECOND_ORDER_REGISTER_GROUP_OP_CODES = [ - (0x00, 0x01, CPU.rotateLeftCircular), - (0x08, 0x01, CPU.rotateRightCircular), - (0x10, 0x01, CPU.rotateLeft), - (0x18, 0x01, CPU.rotateRight), - (0x20, 0x01, CPU.shiftLeftArithmetic), - (0x28, 0x01, CPU.shiftRightArithmetic), + (0x00, 0x01, CPU.rotate_left_circular), + (0x08, 0x01, CPU.rotate_right_circular), + (0x10, 0x01, CPU.rotate_left), + (0x18, 0x01, CPU.rotate_right), + (0x20, 0x01, CPU.shift_left_arithmetic), + (0x28, 0x01, CPU.shift_right_arithmetic), (0x30, 0x01, CPU.swap), - (0x38, 0x01, CPU.shiftWordRightLogical), - (0x40, 0x01, CPU.testBit, range(0, 8), 0x08), - (0xC0, 0x01, CPU.setBit, range(0, 8), 0x08), - (0x80, 0x01, CPU.resetBit, range(0, 8), 0x08) + (0x38, 0x01, CPU.shift_word_right_logical), + (0x40, 0x01, CPU.test_bit, range(0, 8), 0x08), + (0xC0, 0x01, CPU.set_bit, range(0, 8), 0x08), + (0x80, 0x01, CPU.reset_bit, range(0, 8), 0x08) ] # RAW OPCODE TABLE INITIALIZATION ---------------------------------------------- Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboy.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboy.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboy.py Thu May 8 13:54:14 2008 @@ -4,32 +4,32 @@ GameBoy Scheduler and Memory Mapper """ -from pypy.lang.gameboy import constants -from pypy.lang.gameboy.cpu import * +from pypy.lang.gameboy import constants +from pypy.lang.gameboy.cpu import * from pypy.lang.gameboy.cartridge import * from pypy.lang.gameboy.interrupt import * -from pypy.lang.gameboy.joypad import * -from pypy.lang.gameboy.ram import * -from pypy.lang.gameboy.serial import * -from pypy.lang.gameboy.sound import * -from pypy.lang.gameboy.timer import * -from pypy.lang.gameboy.video import * +from pypy.lang.gameboy.joypad import * +from pypy.lang.gameboy.ram import * +from pypy.lang.gameboy.serial import * +from pypy.lang.gameboy.sound import * +from pypy.lang.gameboy.timer import * +from pypy.lang.gameboy.video import * from pypy.lang.gameboy.cartridge import * class GameBoy(object): def __init__(self): - self.createDrivers() - self.createGamboyElements() + self.create_drivers() + self.create_gamboy_elements() - def createDrivers(self): + def create_drivers(self): self.clock = Clock() self.joypadDriver = JoypadDriver() self.videoDriver = VideoDriver() self.soundDriver = SoundDriver() - def createGamboyElements(self): + def create_gamboy_elements(self): self.ram = RAM() self.cartridgeManager = CartridgeManager(self.clock) self.interrupt = Interrupt() @@ -40,21 +40,21 @@ self.video = Video(self.videoDriver, self.interrupt, self) self.sound = Sound(self.soundDriver) - def getCartridgeManager(self): + def get_cartridge_manager(self): return self.cartridgeManager - def loadCartridge(self, cartridge): + def load_cartridge(self, cartridge): self.cartridgeManager.load(cartridge) - self.cpu.setROM(self.cartridgeManager.getROM()) + self.cpu.set_rom(self.cartridgeManager.get_rom()) - def loadCartridgeFile(self, path): - self.loadCartridge(Cartridge(path)) + def load_cartridge_file(self, path): + self.load_cartridge(Cartridge(path)) - def getFrameSkip(self): - return self.video.getFrameSkip() + def get_frame_skip(self): + return self.video.get_frame_skip() - def setFrameSkip(self, frameSkip): - self.video.setFrameSkip(frameSkip) + def set_frame_skip(self, frameSkip): + self.video.set_frame_skip(frameSkip) def save(self, cartridgeName): self.cartridge.save(cartridgeName) @@ -75,17 +75,17 @@ self.joypad.reset() self.video.reset() self.sound.reset() - self.cpu.setROM(self.cartridgeManager.getROM()) + self.cpu.set_rom(self.cartridgeManager.get_rom()) self.drawLogo() - def cycles(self): - return min( self.video.getCycles(), self.serial.getCycles(), - self.timer.getCycles(), self.sound.getCycles(), - self.joypad.getCycles()) + def get_cycles(self): + return min( self.video.get_cycles(), self.serial.get_cycles(), + self.timer.get_cycles(), self.sound.get_cycles(), + self.joypad.get_cycles()) def emulate(self, ticks): while ticks > 0: - count = self.cycles() + count = self.get_cycles() self.cpu.emulate(count) self.serial.emulate(count) self.timer.emulate(count) @@ -95,24 +95,24 @@ ticks -= count def write(self, address, data): - receiver = self.getReceiver(address) + receiver = self.get_receiver(address) if receiver==None: raise Exception("invalid read address given") receiver.write(address, data) def read(self, address): - receiver = self.getReceiver(address) + receiver = self.get_receiver(address) if receiver==None: raise Exception("invalid read address given") return receiver.read(address) - def getReceiver(self, address): + def get_receiver(self, address): if 0x0000 <= address <= 0x7FFF: - return self.cartridgeManager.getMemoryBank() + return self.cartridgeManager.get_memory_bank() elif 0x8000 <= address <= 0x9FFF: return self.video elif 0xA000 <= address <= 0xBFFF: - return self.cartridgeManager.getMemoryBank() + return self.cartridgeManager.get_memory_bank() elif 0xC000 <= address <= 0xFDFF: return self.ram elif 0xFE00 <= address <= 0xFEFF: @@ -134,7 +134,7 @@ elif 0xFFFF <= address <= 0xFFFF: return self.interrupt - def drawLogo(self): + def draw_logo(self): for index in range(0, 48): bits = self.cartridge.read(0x0104 + index) pattern0 = ((bits >> 0) & 0x80) + ((bits >> 1) & 0x60)\ Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboyImplementation.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboyImplementation.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboyImplementation.py Thu May 8 13:54:14 2008 @@ -16,13 +16,14 @@ class GameBoyImplementation(GameBoy): def __init__(self): - self.iniWindow() + self.create_window() GameBoy.__init__(self) - def iniWindow(self): + def create_window(self): self.win = window.Window() + self.win.set_caption("PyBoy a GameBoy (TM)") - def createDrivers(self): + def create_drivers(self): self.clock = Clock() self.joypadDriver = JoypadDriverImplementation(self.win) self.videoDriver = VideoDriverImplementation(self.win) @@ -35,11 +36,11 @@ def __ini__(self, win): JoypadDriver.__ini__(self) - self.crateButtonKeyCodes() + self.create_button_key_codes() self.win = win - self.createListeners() + self.create_listeners() - def crateButtonKeyCodes(self): + def create_button_key_codes(self): self.buttonKeyCodes = {key.UP : (self.buttonUp), key.RIGHT : (self.buttonRight), key.DOWN : (self.buttonDown), @@ -49,21 +50,21 @@ key.A : (self.buttonA), key.B : (self.ButtonB)} - def createListeners(self): + def create_listeners(self): self.win.on_key_press = self.on_key_press self.win.on_key_release = self.on_key_press def on_key_press(symbol, modifiers): - pressButtonFunction = self.getButton(symbol, modifiers) + pressButtonFunction = self.get_button_handler(symbol, modifiers) if pressButtonFunction != None: pressButtonFunction(True) def on_key_release(symbol, modifiers): - pressButtonFunction = self.getButton(symbol, modifiers) + pressButtonFunction = self.get_button_handler(symbol, modifiers) if pressButtonFunction != None: pressButtonFunction(False) - def getButton(self, symbol, modifiers): + def get_button_handler(self, symbol, modifiers): if symbol in self.buttonKeyCodes: if len(self.buttonKeyCodes[symbol]) == 1 or\ self.buttonKeyCodes[symbol][1] == modifiers: @@ -77,14 +78,15 @@ def __init__(self): SoundDriver.__init__(self) - self.createSoundDriver() + self.create_sound_driver() self.enabled = True self.sampleRate = 44100 self.channelCount = 2 self.bitsPerSample = 8 - def createSoundDriver(self): - + def create_sound_driver(self): + pass + def start(self): pass @@ -103,21 +105,22 @@ VideoDriver.__init__(self) self.win = win self.win.on_resize = self.on_resize - self.setWindowSize() - self.createImageBuffer() + self.set_window_size() + self.create_image_buffer() - def createImageBuffer(self): + def create_image_buffer(self): self.buffers = image.get_buffer_manager() self.imageBuffer = self.buffers.get_color_buffer() def on_resize(self, width, height): pass - def setWindowSize(self): + def set_window_size(self): self.win.setSize(self.width, self.height) - def updateDisplay(self): - self.clearPixels() + def update_display(self): + self.imageBuffer.blit(0, 0) + self.win.flip() # ============================================================================== Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/interrupt.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/interrupt.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/interrupt.py Thu May 8 13:54:14 2008 @@ -10,13 +10,13 @@ self.reset() def reset(self): - self._isPending = self._reset + self.isPending = self._reset - def isPending(self): - return self._isPending + def is_pending(self): + return self.isPending - def setPending(self, _isPending=True): - self._isPending = _isPending + def set_pending(self, isPending=True): + self.isPending = isPending class Interrupt(object): @@ -27,26 +27,26 @@ """ def __init__(self): - self.createInterruptFlags() - self.createFlagList() - self.createFlagMaskMapping() + self.create_interrupt_flags() + self.createvflag_list() + self.create_flag_mask_mapping() self.reset() - def createInterruptFlags(self): + def create_interrupt_flags(self): self.vBlank = InterruptFlag(True, constants.VBLANK, 0x40) self.lcd = InterruptFlag(False, constants.LCD, 0x48) self.timer = InterruptFlag(False, constants.TIMER, 0x50) self.serial = InterruptFlag(False, constants.SERIAL, 0x58) self.joypad = InterruptFlag(False, constants.JOYPAD, 0x60) - def createFlagList(self): + def createvflag_list(self): self.interruptFlags = [ self.vBlank, self.lcd, self.timer, self.serial, self.joypad ] - def createFlagMaskMapping(self): + def create_flag_mask_mapping(self): self.maskMapping = {} for flag in self.interruptFlags: self.maskMapping[flag.mask] = flag @@ -56,51 +56,51 @@ for flag in self.interruptFlags: flag.reset() - def isPending(self, mask=None): + def is_pending(self, mask=None): if not self.enable: return False if mask==None: - return self.vBlank.isPending() - elif self.vBlank.isPending(): - return self.maskMapping[mask].isPending() + return self.vBlank.is_pending() + elif self.vBlank.is_pending(): + return self.maskMapping[mask].is_pending() else: return False - def raiseInterrupt(self, mask): - self.maskMapping[mask].setPending(True) + def raise_interrupt(self, mask): + self.maskMapping[mask].set_pending(True) def lower(self, mask): - self.maskMapping[mask].setPending(False) + self.maskMapping[mask].set_pending(False) def write(self, address, data): if address == constants.IE: - self.setInterruptEnable(data) + self.set_interrupt_enable(data) elif address == constants.IF: - self.setInterruptFlag(data) + self.set_fnterrupt_flag(data) def read(self, address): if address == constants.IE: - return self.getInterruptEnable() + return self.get_interrupt_enable() elif address == constants.IF: - return self.getInterruptFlag() + return self.get_interrupt_flag() return 0xFF - def getInterruptEnable(self): + def get_interrupt_enable(self): return int(self.enable) - def setInterruptEnable(self, isEnabled=True): + def set_interrupt_enable(self, isEnabled=True): self.enable = bool(isEnabled) - def getInterruptFlag(self): + def get_interrupt_flag(self): flag = 0x00 for interruptFlag in self.interruptFlags: - if interruptFlag.isPending(): + if interruptFlag.is_pending(): flag |= interruptFlag.mask return 0xE0 | flag - def setInterruptFlag(self, data): + def set_fnterrupt_flag(self, data): for flag in self.interruptFlags: if (data & flag.mask) != 0: - flag.setPending(True) + flag.set_pending(True) else: - flag.setPending(False) + flag.set_pending(False) Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/joypad.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/joypad.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/joypad.py Thu May 8 13:54:14 2008 @@ -18,13 +18,13 @@ self.buttonCode = 0xF self.cycles = constants.JOYPAD_CLOCK - def getCycles(self): + def get_cycles(self): return self.cycles def emulate(self, ticks): self.cycles -= ticks if self.cycles <= 0: - if self.driver.isRaised(): + if self.driver.is_raised(): self.update() self.cycles = constants.JOYPAD_CLOCK @@ -41,14 +41,13 @@ def update(self): oldButtons = self.buttonCode if self.joyp == 0x1: - self.buttonCode = self.driver.getButtonCode() + self.buttonCode = self.driver.get_button_code() elif self.joyp == 0x2: - self.buttonCode = self.driver.getDirectionCode() + self.buttonCode = self.driver.get_direction_code() else: self.buttonCode = 0xF - if oldButtons != self.buttonCode: - self.interrupt.raiseInterrupt(constants.JOYPAD) + self.interrupt.raise_interrupt(constants.JOYPAD) # ------------------------------------------------------------------------------ @@ -60,10 +59,10 @@ """ def __init__(self): self.raised = False - self.createButtons() + self.create_buttons() self.reset() - def createButtons(self): + def create_buttons(self): self.up = Button(constants.BUTTON_UP) self.right = Button(constants.BUTTON_RIGHT) self.down = Button(constants.BUTTON_DOWN) @@ -72,92 +71,92 @@ self.select = Button(constants.BUTTON_SELECT) self.a = Button(constants.BUTTON_A) self.b = Button(constants.BUTTON_B) - self.addOppositeButtons() - self.createButtonGroups() + self.add_opposite_buttons() + self.create_button_groups() - def addOppositeButtons(self): + def add_opposite_buttons(self): self.up.oppositeButton = self.down self.down.oppositeButton = self.up self.left.oppositeButton = self.right self.right.oppositeButton = self.left - def createButtonGroups(self): + def create_button_groups(self): self.directions = [self.up, self.right, self.down, self.left] self.buttons = [self.start, self.select, self.a, self.b] - def getButtons(self): + def get_buttons(self): return self.buttons - def getDirections(self): + def get_directions(self): return self.directions - def getButtonCode(self): + def get_button_code(self): code = 0 for button in self.buttons: - code |= button.getCode() + code |= button.get_code() return code - def getDirectionCode(self): + def get_direction_code(self): code = 0 for button in self.directions: - code |= button.getCode() + code |= button.get_code() return code - def isRaised(self): + def is_raised(self): raised = self.raised self.raised = False return raised def reset(self): self.raised = False - self.releaseAllButtons() + self.release_all_buttons() - def releaseAllButtons(self): - self.releaseButtons() - self.releaseDirections() + def release_all_buttons(self): + self.release_buttons() + self.release_directions() - def releaseButtons(self): + def release_buttons(self): self.up.release() self.right.release() self.down.release() self.left.release() - def releaseDirections(self): + def release_directions(self): self.start.release() self.select.release() self.a.release() self.b.release() - def buttonUp(self, pressed=True): - self.up.toggleButton(pressed) + def button_up(self, pressed=True): + self.up.toggle_button(pressed) self.raised = True - def buttonRight(self, pressed=True): - self.right.toggleButton(pressed) + def button_right(self, pressed=True): + self.right.toggle_button(pressed) self.raised = True - def buttonDown(self, pressed=True): - self.down.toggleButton(pressed) + def button_down(self, pressed=True): + self.down.toggle_button(pressed) self.raised = True - def buttonLeft(self, pressed=True): - self.left.toggleButton(pressed) + def button_left(self, pressed=True): + self.left.toggle_button(pressed) self.raised = True - def buttonStart(self, pressed=True): - self.start.toggleButton(pressed) + def button_start(self, pressed=True): + self.start.toggle_button(pressed) self.raised = True - def buttonSelect(self, pressed=True): - self.select.toggleButton(pressed) + def button_select(self, pressed=True): + self.select.toggle_button(pressed) self.raised = True - def buttonA(self, pressed=True): - self.a.toggleButton(pressed) + def button_a(self, pressed=True): + self.a.toggle_button(pressed) self.raised = True - def buttonB(self, pressed=True): - self.b.toggleButton(pressed) + def button_b(self, pressed=True): + self.b.toggle_button(pressed) self.raised = True @@ -171,13 +170,13 @@ self.oppositeButton = oppositeButton self.pressed = False - def getCode(self): + def get_code(self): if self.pressed: return self.codeValue else: return 0 - def toggleButton(self, pressed=True): + def toggle_button(self, pressed=True): if pressed: self.press() else: @@ -191,5 +190,5 @@ self.oppositeButton.release() self.pressed = True - def isPressed(self): + def is_pressed(self): return self.pressed \ No newline at end of file Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/serial.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/serial.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/serial.py Thu May 8 13:54:14 2008 @@ -1,3 +1,4 @@ + from pypy.lang.gameboy import constants class Serial(object): @@ -15,7 +16,7 @@ self.sb = 0x00 self.sc = 0x00 - def getCycles(self): + def get_cycles(self): return self.cycles def emulate(self, ticks): @@ -26,32 +27,32 @@ self.sb = 0xFF self.sc &= 0x7F self.cycles = constants.SERIAL_IDLE_CLOCK - self.interrupt.raiseInterrupt(constants.SERIAL) + self.interrupt.raise_interrupt(constants.SERIAL) - def setSerialData(self, data): + def set_serial_data(self, data): self.sb = data - def setSerialControl(self, data): + def set_serial_control(self, data): self.sc = data # HACK: delay the serial interrupt (Shin Nihon Pro Wrestling) self.cycles = constants.SERIAL_IDLE_CLOCK + constants.SERIAL_CLOCK - def getSerialData(self): + def get_serial_data(self): return self.sb - def getSerialControl(self): + def get_serial_control(self): return self.sc def write(self, address, data): if address == constants.SB: - self.setSerialData(data) + self.set_serial_data(data) elif address == constants.SC: - self.setSerialControl(data) + self.set_serial_control(data) def read(self, address): if address == constants.SB: - return self.getSerialData() + return self.get_serial_data() elif address == constants.SC: - return self.getSerialControl() + return self.get_serial_control() else: return 0xFF \ No newline at end of file Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py Thu May 8 13:54:14 2008 @@ -32,16 +32,16 @@ def reset(self): self.audioIndex = 0 - def getAudioLength(self): + def get_audio_length(self): return self.audioLength - def getAudioEnvelope(self): + def get_audio_envelope(self): return self.audioEnvelope - def getAudioFrequency(self): + def get_audio_frequency(self): return self.audioFrequency - def getAudioPlayback(self): + def get_audio_playback(self): return self.audioPlayback @@ -62,45 +62,52 @@ self.audio1Frequency=0 # Audio Channel 1 - def getAudioSweep(self): + def get_audio_sweep(self): return self.audioSweep - def setAudioSweep(self, data): + def set_audio_sweep(self, data): self.audioSweep = data - self.audioSweepLength = (constants.SOUND_CLOCK / 128) * ((self.audioSweep >> 4) & 0x07) + self.audioSweepLength = (constants.SOUND_CLOCK / 128) * \ + ((self.audioSweep >> 4) & 0x07) - def setAudioLength(self, data): + def set_audio_length(self, data): self.audioLength = data - self.audio1Length = (constants.SOUND_CLOCK / 256) * (64 - (self.audioLength & 0x3F)) + self.audio1Length = (constants.SOUND_CLOCK / 256) * \ + (64 - (self.audioLength & 0x3F)) - def setAudioEnvelope(self, data): + def set_audio_envelope(self, data): self.audioEnvelope = data if (self.audioPlayback & 0x40) != 0: return if (self.audioEnvelope >> 4) == 0: self.audioVolume = 0 - elif self.audio1EnvelopeLength == 0 and (self.audioEnvelope & 0x07) == 0: + elif self.audio1EnvelopeLength == 0 and \ + (self.audioEnvelope & 0x07) == 0: self.audioVolume = (self.audioVolume + 1) & 0x0F else: self.audioVolume = (self.audioVolume + 2) & 0x0F - def setAudioFrequency(self, data): + def set_audio_frequency(self, data): self.audioFrequency = data - self.audio1Frequency = self.frequencyTable[self.audioFrequency + ((self.audioPlayback & 0x07) << 8)] + index = self.audioFrequency + ((self.audioPlayback & 0x07) << 8) + self.audio1Frequency = self.frequencyTable[index] - def setAudioPlayback(self, data): + def set_audio_playback(self, data): self.audioPlayback = data self.audio1Frequency = self.frequencyTable[self.audioFrequency + ((self.audioPlayback & 0x07) << 8)] if (self.audioPlayback & 0x80) != 0: self.enabled = True if (self.audioPlayback & 0x40) != 0 and self.audio1Length == 0: - self.audio1Length = (constants.SOUND_CLOCK / 256) * (64 - (self.audioLength & 0x3F)) - self.audioSweepLength = (constants.SOUND_CLOCK / 128) * ((self.audioSweep >> 4) & 0x07) + self.audio1Length = (constants.SOUND_CLOCK / 256) * \ + (64 - (self.audioLength & 0x3F)) + self.audioSweepLength = (constants.SOUND_CLOCK / 128) * \ + ((self.audioSweep >> 4) & 0x07) self.audioVolume = self.audioEnvelope >> 4 - self.audio1EnvelopeLength = (constants.SOUND_CLOCK / 64) * (self.audioEnvelope & 0x07) + self.audio1EnvelopeLength = (constants.SOUND_CLOCK / 64) * \ + (self.audioEnvelope & 0x07) - def updateAudio(self): + def update_audio(self): if (self.audioPlayback & 0x40) != 0 and self.audio1Length > 0: self.audio1Length-=1 if self.audio1Length <= 0: @@ -113,13 +120,15 @@ self.audioVolume+=1 elif self.audioVolume > 0: self.audioVolume-=1 - self.audio1EnvelopeLength += (constants.SOUND_CLOCK / 64) * (self.audioEnvelope & 0x07) + self.audio1EnvelopeLength += (constants.SOUND_CLOCK / 64) * \ + (self.audioEnvelope & 0x07) if self.audioSweepLength > 0: self.audioSweepLength-=1 if self.audioSweepLength <= 0: sweepSteps = (self.audioSweep & 0x07) if sweepSteps != 0: - frequency = ((self.audioPlayback & 0x07) << 8) + self.audioFrequency + frequency = ((self.audioPlayback & 0x07) << 8) + \ + self.audioFrequency if (self.audioSweep & 0x08) != 0: frequency -= frequency >> sweepSteps else: @@ -127,13 +136,15 @@ if frequency < 2048: self.audio1Frequency = self.frequencyTable[frequency] self.audioFrequency = frequency & 0xFF - self.audioPlayback = (self.audioPlayback & 0xF8) + ((frequency >> 8) & 0x07) + self.audioPlayback = (self.audioPlayback & 0xF8) + \ + ((frequency >> 8) & 0x07) else: self.audio1Frequency = 0 self.outputEnable &= ~0x01 - self.audioSweepLength += (constants.SOUND_CLOCK / 128) * ((self.audioSweep >> 4) & 0x07) + self.audioSweepLength += (constants.SOUND_CLOCK / 128) * \ + ((self.audioSweep >> 4) & 0x07) - def mixAudio(self, buffer, length): + def mix_audio(self, buffer, length): wavePattern = 0x18 if (self.audioLength & 0xC0) == 0x00: wavePattern = 0x04 @@ -169,53 +180,57 @@ self.audio2Frequency=0 # Audio Channel 2 - def setAudioLength(self, data): + def set_audio_length(self, data): self.audioLength = data - self.audio2Length = (constants.SOUND_CLOCK / 256) * (64 - (self.audioLength & 0x3F)) + self.audio2Length = (constants.SOUND_CLOCK / 256) * \ + (64 - (self.audioLength & 0x3F)) - def setAudioEnvelope(self, data): + def set_audio_envelope(self, data): self.audioEnvelope = data if (self.audioPlayback & 0x40) == 0: if (self.audioEnvelope >> 4) == 0: self.audioVolume = 0 - elif self.audio2EnvelopeLength == 0 and (self.audioEnvelope & 0x07) == 0: + elif self.audio2EnvelopeLength == 0 and \ + (self.audioEnvelope & 0x07) == 0: self.audioVolume = (self.audioVolume + 1) & 0x0F else: self.audioVolume = (self.audioVolume + 2) & 0x0F - def setAudioFrequency(self, data): + def set_audio_frequency(self, data): self.audioFrequency = data self.audio2Frequency = self.frequencyTable[self.audioFrequency\ + ((self.audioPlayback & 0x07) << 8)] - def setAudioPlayback(self, data): + def set_audio_playback(self, data): self.audioPlayback = data self.audio2Frequency = self.frequencyTable[self.audioFrequency\ + ((self.audioPlayback & 0x07) << 8)] if (self.audioPlayback & 0x80) != 0: self.enabled = True if (self.audioPlayback & 0x40) != 0 and self.audio2Length == 0: - self.audio2Length = (constants.SOUND_CLOCK / 256) * (64 - (self.audioLength & 0x3F)) + self.audio2Length = (constants.SOUND_CLOCK / 256) * \ + (64 - (self.audioLength & 0x3F)) self.audioVolume = self.audioEnvelope >> 4 - self.audio2EnvelopeLength = (constants.SOUND_CLOCK / 64) * (self.audioEnvelope & 0x07) + self.audio2EnvelopeLength = (constants.SOUND_CLOCK / 64) * \ + (self.audioEnvelope & 0x07) - def updateAudio(self): + def update_audio(self): if (self.audioPlayback & 0x40) != 0 and self.audio2Length > 0: self.audio2Length-=1 if self.audio2Length <= 0: self.enabled = False if self.audio2EnvelopeLength > 0: self.audio2EnvelopeLength-=1 - if self.audio2EnvelopeLength <= 0: if (self.audioEnvelope & 0x08) != 0: if self.audioVolume < 15: self.audioVolume+=1 elif self.audioVolume > 0: self.audioVolume-=1 - self.audio2EnvelopeLength += (constants.SOUND_CLOCK / 64) * (self.audioEnvelope & 0x07) + self.audio2EnvelopeLength += (constants.SOUND_CLOCK / 64) *\ + (self.audioEnvelope & 0x07) - def mixAudio(self, buffer, length): + def mix_audio(self, buffer, length): wavePattern = 0x18 if (self.audioLength & 0xC0) == 0x00: wavePattern = 0x04 @@ -243,7 +258,7 @@ #SquareWaveGenerator class Channel3(Channel): - # Audio Channel 3 int + def __init__(self, sampleRate, frequencyTable): Channel.__init__(self, sampleRate, frequencyTable) self.audioEnable=0 @@ -252,56 +267,58 @@ self.audio3Length=0 self.audio3Frequency=0 self.audioWavePattern = [0]*16 - - # Audio Channel 3 - def getAudioEnable(self): + def get_audio_enable(self): return self.audioEnable - def getAudioLevel(self): + def get_audio_level(self): return self.audioLevel #FIXME strange number here - def getAudio4Frequency(self): + def get_audio_4_frequency(self): return self.audioFrequency - def setAudioEnable(self, data): + def set_audio_enable(self, data): self.audioEnable = data & 0x80 if (self.audioEnable & 0x80) == 0: self.enabled = False - def setAudioLength(self, data): + def set_audio_length(self, data): self.audioLength = data - self.audio3Length = (constants.SOUND_CLOCK / 256) * (256 - self.audioLength) + self.audio3Length = (constants.SOUND_CLOCK / 256) * \ + (256 - self.audioLength) - def setAudioLevel(self, data): + def set_audio_level(self, data): self.audioLevel = data - def setAudioFrequency(self, data): + def set_audio_frequency(self, data): self.audioFrequency = data - self.audio3Frequency = self.frequencyTable[((self.audioPlayback & 0x07) << 8) + self.audioFrequency] >> 1 + index = ((self.audioPlayback & 0x07) << 8) + self.audioFrequency + self.audio3Frequency = self.frequencyTable[index] >> 1 - def setAudioPlayback(self, data): + def set_audio_playback(self, data): self.audioPlayback = data - self.audio3Frequency = self.frequencyTable[((self.audioPlayback & 0x07) << 8) + self.audioFrequency] >> 1 + index = ((self.audioPlayback & 0x07) << 8) + self.audioFrequency + self.audio3Frequency = self.frequencyTable[index] >> 1 if (self.audioPlayback & 0x80) != 0 and (self.audioEnable & 0x80) != 0: self.enabled = True if (self.audioPlayback & 0x40) != 0 and self.audio3Length == 0: - self.audio3Length = (constants.SOUND_CLOCK / 256) * (256 - self.audioLength) + self.audio3Length = (constants.SOUND_CLOCK / 256) *\ + (256 - self.audioLength) - def setAudioWavePattern(self, address, data): + def set_audio_wave_pattern(self, address, data): self.audioWavePattern[address & 0x0F] = data - def getAudioWavePattern(self, address): + def get_audio_wave_pattern(self, address): return self.audioWavePattern[address & 0x0F] & 0xFF - def updateAudio(self): + def update_audio(self): if (self.audioPlayback & 0x40) != 0 and self.audio3Length > 0: self.audio3Length-=1 if self.audio3Length <= 0: self.outputEnable &= ~0x04 - def mixAudio(self, buffer, length): + def mix_audio(self, buffer, length): wavePattern = 2 if (self.audioLevel & 0x60) == 0x00: wavePattern = 8 @@ -339,92 +356,99 @@ self.audio4EnvelopeLength=0 self.audio4Frequency=0 - self.generateNoiseFrequencyRatioTable() - self.generateNoiseTables() - + self.generate_noise_frequency_ratio_table() + self.generate_noise_tables() - def generateNoiseFrequencyRatioTable(self): - self.noiseFreqRatioTable = [0] * 8 + def generate_noise_frequency_ratio_table(self): # Polynomial Noise Frequency Ratios # 4194304 Hz * 1/2^3 * 2 4194304 Hz * 1/2^3 * 1 4194304 Hz * 1/2^3 * # 1/2 4194304 Hz * 1/2^3 * 1/3 4194304 Hz * 1/2^3 * 1/4 4194304 Hz * # 1/2^3 * 1/5 4194304 Hz * 1/2^3 * 1/6 4194304 Hz * 1/2^3 * 1/7 + self.noiseFreqRatioTable = [0] * 8 sampleFactor = ((1 << 16) / self.sampleRate) for ratio in range(0, 8): divider = 1 if ratio != 0: divider = 2 * ratio - self.noiseFreqRatioTable[ratio] = (constants.GAMEBOY_CLOCK / divider) *sampleFactor + self.noiseFreqRatioTable[ratio] = (constants.GAMEBOY_CLOCK / \ + divider) *sampleFactor - # Noise Generation - def generateNoiseTables(self): - self.create7StepNoiseTable() - self.create15StepNoiseTable() + def generate_noise_tables(self): + self.create_7_step_noise_table() + self.create_15_step_noise_table() - def create7StepNoiseTable(self): + def create_7_step_noise_table(self): # Noise Tables - self. noiseStep7Table = [0]*4 #= new int[128 / 32] + self. noiseStep7Table = [0]*4 polynomial = 0x7F # 7 steps for index in range(0, 0x7F): - polynomial = (((polynomial << 6) ^ (polynomial << 5)) & 0x40) | (polynomial >> 1) + polynomial = (((polynomial << 6) ^ (polynomial << 5)) & 0x40) | \ + (polynomial >> 1) if (index & 31) == 0: self.noiseStep7Table[index >> 5] = 0 - self.noiseStep7Table[index >> 5] |= (polynomial & 1) << (index & 31) + self.noiseStep7Table[index >> 5] |= (polynomial & 1) << \ + (index & 31) - def create15StepNoiseTable(self): + def create_15_step_noise_table(self): # 15 steps& - - self.noiseStep15Table = [0]*1024 #= new int[32768 / 32] + self.noiseStep15Table = [0]*1024 polynomial = 0x7FFF for index in range(0, 0x7FFF): - polynomial = (((polynomial << 14) ^ (polynomial << 13)) & 0x4000) | (polynomial >> 1) + polynomial = (((polynomial << 14) ^ (polynomial << 13)) & \ + 0x4000) | (polynomial >> 1) if (index & 31) == 0: self.noiseStep15Table[index >> 5] = 0 - self.noiseStep15Table[index >> 5] |= (polynomial & 1) << (index & 31) + self.noiseStep15Table[index >> 5] |= (polynomial & 1) << \ + (index & 31) # Audio Channel 4 - def getAudioLength(self): + def get_audio_length(self): return self.audioLength - def getAudioPolynomial(self): + def get_audio_polynomial(self): return self.audioPolynomial - def getAudioPlayback(self): + def get_audio_playback(self): return self.audioPlayback - def setAudioLength(self, data): + def set_audio_length(self, data): self.audioLength = data - self.audio4Length = (constants.SOUND_CLOCK / 256) * (64 - (self.audioLength & 0x3F)) + self.audio4Length = (constants.SOUND_CLOCK / 256) * \ + (64 - (self.audioLength & 0x3F)) - def setAudioEnvelope(self, data): + def set_audio_envelope(self, data): self.audioEnvelope = data if (self.audioPlayback & 0x40) == 0: if (self.audioEnvelope >> 4) == 0: self.audioVolume = 0 - elif self.audio4EnvelopeLength == 0 and (self.audioEnvelope & 0x07) == 0: + elif self.audio4EnvelopeLength == 0 and \ + (self.audioEnvelope & 0x07) == 0: self.audioVolume = (self.audioVolume + 1) & 0x0F else: self.audioVolume = (self.audioVolume + 2) & 0x0F - def setAudioPolynomial(self, data): + def set_audio_polynomial(self, data): self.audioPolynomial = data if (self.audioPolynomial >> 4) <= 12: - self.audio4Frequency = self.noiseFreqRatioTable[self.audioPolynomial & 0x07] >> ((self.audioPolynomial >> 4) + 1) + freq = self.noiseFreqRatioTable[self.audioPolynomial & 0x07] + self.audio4Frequency = freq >> ((self.audioPolynomial >> 4) + 1) else: self.audio4Frequency = 0 - def setAudioPlayback(self, data): + def set_audio_playback(self, data): self.audioPlayback = data if (self.audioPlayback & 0x80) != 0: self.enabled = True if (self.audioPlayback & 0x40) != 0 and self.audio4Length == 0: - self.audio4Length = (constants.SOUND_CLOCK / 256) * (64 - (self.audioLength & 0x3F)) + self.audio4Length = (constants.SOUND_CLOCK / 256) * \ + (64 - (self.audioLength & 0x3F)) self.audioVolume = self.audioEnvelope >> 4 - self.audio4EnvelopeLength = (constants.SOUND_CLOCK / 64) * (self.audioEnvelope & 0x07) + self.audio4EnvelopeLength = (constants.SOUND_CLOCK / 64) * \ + (self.audioEnvelope & 0x07) self.audio4Index = 0 - def updateAudio(self): + def update_audio(self): if (self.audioPlayback & 0x40) != 0 and self.audio4Length > 0: self.audio4Length-=1 if self.audio4Length <= 0: @@ -437,20 +461,23 @@ self.audioVolume+=1 elif self.audioVolume > 0: self.audioVolume-=1 - self.audio4EnvelopeLength += (constants.SOUND_CLOCK / 64) * (self.audioEnvelope & 0x07) + self.audio4EnvelopeLength += (constants.SOUND_CLOCK / 64) *\ + (self.audioEnvelope & 0x07) - def mixAudio(self, buffer, length): + def mix_audio(self, buffer, length): for index in range(0, length, 2): self.audio4Index += self.audio4Frequency polynomial if (self.audioPolynomial & 0x08) != 0: # 7 steps self.audio4Index &= 0x7FFFFF - polynomial = self.noiseStep7Table[self.audio4Index >> 21] >> ((self.audio4Index >> 16) & 31) + polynomial = self.noiseStep7Table[self.audio4Index >> 21] >>\ + ((self.audio4Index >> 16) & 31) else: # 15 steps self.audio4Index &= 0x7FFFFFFF - polynomial = self.noiseStep15Table[self.audio4Index >> 21] >> ((self.audio4Index >> 16) & 31) + polynomial = self.noiseStep15Table[self.audio4Index >> 21] >> \ + ((self.audio4Index >> 16) & 31) if (polynomial & 1) != 0: if (self.outputTerminal & 0x80) != 0: buffer[index + 0] -= self.audioVolume @@ -476,25 +503,26 @@ self.outputEnable=0 self.driver = soundDriver - self.sampleRate = self.driver.getSampleRate() + self.sampleRate = self.driver.get_sample_rate() - self.generateFrequencyTable() - self.createAudioChannels() + self.generate_frequency_table() + self.create_audio_channels() self.reset() - def createAudioChannels(self): + def create_audio_channels(self): self.channel1 = Channel1(self.sampleRate, self.frequencyTable) self.channel2 = Channel2(self.sampleRate, self.frequencyTable) self.channel3 = Channel3(self.sampleRate, self.frequencyTable) self.channel4 = NoiseGenerator(self.sampleRate, self.frequencyTable) - def generateFrequencyTable(self): + def generate_frequency_table(self): self.frequencyTable = [0] * 2048 # frequency = (4194304 / 32) / (2048 - period) Hz for period in range(0, 2048): - skip = (((constants.GAMEBOY_CLOCK << 10) / self.sampleRate) << 16) / (2048 - period) + skip = (((constants.GAMEBOY_CLOCK << 10) / \ + self.sampleRate) << 16) / (2048 - period) if skip >= (32 << 22): self.frequencyTable[period] = 0 else: @@ -551,178 +579,178 @@ def stop(self): self.driver.stop() - def getCycles(self): + def get_cycles(self): return self.cycles def emulate(self, ticks): self.cycles -= ticks while (self.cycles <= 0): - self.updateAudio() + self.update_audio() if self.driver.isEnabled(): - self.mixDownAudio() + self.mix_down_audio() self.cycles += constants.GAMEBOY_CLOCK / constants.SOUND_CLOCK - def mixDownAudio(self): - self.frames += self.driver.getSampleRate() + def mix_down_audio(self): + self.frames += self.driver.get_sample_rate() length = (self.frames / constants.SOUND_CLOCK) << 1 - self.mixAudio(self.buffer, length) + self.mix_audio(self.buffer, length) self.driver.write(self.buffer, length) self.frames %= constants.SOUND_CLOCK def read(self, address): if address==constants.NR10: - return self.channel1.getAudioSweep() + return self.channel1.get_audio_sweep() elif address == constants.NR11: - return self.channel1.getAudioLength() + return self.channel1.get_audio_length() elif address == constants.NR12: - return self.channel1.getAudioEnvelope() + return self.channel1.get_audio_envelope() elif address == constants.NR13: - return self.channel1.getAudioFrequency() + return self.channel1.get_audio_frequency() elif address == constants.NR14: - return self.channel1.getAudioPlayback() + return self.channel1.get_audio_playback() elif address == constants.NR21: - return self.channel2.getAudioLength() + return self.channel2.get_audio_length() elif address == constants.NR22: - return self.channel2.getAudioEnvelope() + return self.channel2.get_audio_envelope() elif address==constants.NR23: - return self.channel2.getAudioFrequency() + return self.channel2.get_audio_frequency() elif address==constants.NR24: - return self.channel2.getAudioPlayback() + return self.channel2.get_audio_playback() elif address==constants.NR30: - return self.channel3.getAudioEnable() + return self.channel3.get_audio_enable() elif address==constants.NR31: - return self.channel3.getAudioLength() + return self.channel3.get_audio_length() elif address==constants.NR32: - return self.channel3.getAudioLevel() + return self.channel3.get_audio_level() elif address==constants.NR33: - return self.channel4.getAudioFrequency() + return self.channel4.get_audio_frequency() elif address==constants.NR34: - return self.channel3.getAudioPlayback() + return self.channel3.get_audio_playback() elif address==constants.NR41: - return self.channel4.getAudioLength() + return self.channel4.get_audio_length() elif address==constants.NR42: - return self.channel4.getAudioEnvelope() + return self.channel4.get_audio_envelope() elif address==constants.NR43: - return self.channel4.getAudioPolynomial() + return self.channel4.get_audio_polynomial() elif address==constants.NR44: - return self.channel4.getAudioPlayback() + return self.channel4.get_audio_playback() elif address==constants.NR50: - return self.getOutputLevel() + return self.get_output_level() elif address==constants.NR51: - return self.getOutputTerminal() + return self.get_output_terminal() elif address==constants.NR52: - return self.getOutputEnable() + return self.get_output_enable() - elif (address >= constants.AUD3WAVERAM and address <= constants.AUD3WAVERAM + 0x3F): - return self.channel3.getAudioWavePattern(address) + elif address >= constants.AUD3WAVERAM and \ + address <= constants.AUD3WAVERAM + 0x3F: + return self.channel3.get_audio_wave_pattern(address) return 0xFF def write(self, address, data): if address==constants.NR10: - self.channel1.setAudioSweep(data) + self.channel1.set_audio_sweep(data) elif address == constants.NR11: - self.channel1.setAudioLength(data) + self.channel1.set_audio_length(data) elif address == constants.NR12: - self.channel1.setAudioEnvelope(data) + self.channel1.set_audio_envelope(data) elif address == constants.NR13: - self.channel1.setAudioFrequency(data) + self.channel1.set_audio_frequency(data) elif address == constants.NR14: - self.channel1.setAudioPlayback(data) + self.channel1.set_audio_playback(data) elif address == constants.NR21: - self.channel2.setAudioLength(data) + self.channel2.set_audio_length(data) elif address == constants.NR22: - self.channel2.setAudioEnvelope(data) + self.channel2.set_audio_envelope(data) elif address == constants.NR23: - self.channel2.setAudioFrequency(data) + self.channel2.set_audio_frequency(data) elif address == constants.NR24: - self.channel2.setAudioPlayback(data) + self.channel2.set_audio_playback(data) elif address == constants.NR30: - self.channel3.setAudioEnable(data) + self.channel3.set_audio_enable(data) elif address == constants.NR31: - self.channel3.setAudioLength(data) + self.channel3.set_audio_length(data) elif address == constants.NR32: - self.channel3.setAudioLevel(data) + self.channel3.set_audio_level(data) elif address == constants.NR33: - self.channel3.setAudioFrequency(data) + self.channel3.set_audio_frequency(data) elif address == constants.NR34: - self.channel3.setAudioPlayback(data) + self.channel3.set_audio_playback(data) elif address == constants.NR41: - self.channel4.setAudioLength(data) + self.channel4.set_audio_length(data) elif address == constants.NR42: - self.channel4.setAudioEnvelope(data) + self.channel4.set_audio_envelope(data) elif address == constants.NR43: - self.channel4.setAudioPolynomial(data) + self.channel4.set_audio_polynomial(data) elif address == constants.NR44: - self.channel4.setAudioPlayback(data) + self.channel4.set_audio_playback(data) elif address == constants.NR50: - self.setOutputLevel(data) + self.set_output_level(data) elif address == constants.NR51: - self.setOutputTerminal(data) + self.set_output_terminal(data) elif address == constants.NR52: - self.setOutputEnable(data) + self.set_output_enable(data) - elif (address >= constants.AUD3WAVERAM and address <= constants.AUD3WAVERAM + 0x3F): - self.channel3.setAudioWavePattern(address, data) + elif address >= constants.AUD3WAVERAM and \ + address <= constants.AUD3WAVERAM + 0x3F: + self.channel3.set_audio_wave_pattern(address, data) - def updateAudio(self): + def update_audio(self): if (self.outputEnable & 0x80) == 0: return if (self.outputEnable & 0x01) != 0: - self.channel1.updateAudio() + self.channel1.update_audio() if (self.outputEnable & 0x02) != 0: - self.channel2.updateAudio() + self.channel2.update_audio() if (self.outputEnable & 0x04) != 0: - self.channel3.updateAudio() + self.channel3.update_audio() if (self.outputEnable & 0x08) != 0: - self.channel4.updateAudio() + self.channel4.update_audio() - def mixAudio(self, buffer, length): + def mix_audio(self, buffer, length): if (self.outputEnable & 0x80) == 0: return if (self.outputEnable & 0x01) != 0: - self.channel1.mixAudio(buffer, length) + self.channel1.mix_audio(buffer, length) if (self.outputEnable & 0x02) != 0: - self.channel2.mixAudio(buffer, length) + self.channel2.mix_audio(buffer, length) if (self.outputEnable & 0x04) != 0: - self.channel3.mixAudio(buffer, length) + self.channel3.mix_audio(buffer, length) if (self.outputEnable & 0x08) != 0: - self.channel4.mixAudio(buffer, length) + self.channel4.mix_audio(buffer, length) # Output Control - def getOutputLevel(self): + def get_output_level(self): return self.outputLevel - def getOutputTerminal(self): + def get_output_terminal(self): return self.outputTerminal - def getOutputEnable(self): + def get_output_enable(self): return self.outputEnable - def setOutputLevel(self, data): + def set_output_level(self, data): self.outputLevel = data - def setOutputTerminal(self, data): + def set_output_terminal(self, data): self.outputTerminal = data - def setOutputEnable(self, data): + def set_output_enable(self, data): self.outputEnable = (self.outputEnable & 0x7F) | (data & 0x80) - if ((self.outputEnable & 0x80) == 0x00): + if (self.outputEnable & 0x80) == 0x00: self.outputEnable &= 0xF0 - - - # SOUND DRIVER ----------------------------------------------------------------- + class SoundDriver(object): def __init__(self): @@ -731,16 +759,16 @@ self.channelCount = 2 self.bitsPerSample = 8 - def isEnabled(self): + def is_enabled(self): return self.enabled - def getSampleRate(self): + def get_sample_rate(self): return self.sampleRate - def getChannels(self): + def get_channels(self): return self.channelCount - def getBitsPerSample(self): + def get_bits_per_sample(self): return self.bitsPerSample def start(self): Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cartridge.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cartridge.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cartridge.py Thu May 8 13:54:14 2008 @@ -64,7 +64,7 @@ assert cartridge.batteryName == romFile+constants.BATTERY_FILE_EXTENSION assert cartridge.batteryFilePath == romFilePath+constants.BATTERY_FILE_EXTENSION - assert cartridge.hasBattery() == False + assert cartridge.has_battery() == False assert cartridge.batteryFile == None @@ -75,7 +75,7 @@ romFilePath = ROM_PATH+"/rom1/"+romName cartridge.load(romFilePath) - assert cartridge.hasBattery() == False + assert cartridge.has_battery() == False def test_cartridge_read(): @@ -92,17 +92,17 @@ romFilePath = ROM_PATH + "/rom1/"+romName cartridge.load(romFilePath) - cartridge.removeBattery() - assert cartridge.hasBattery() == False + cartridge.remove_battery() + assert cartridge.has_battery() == False - cartridge.writeBattery(MAPPED_CONTENT) - assert cartridge.hasBattery() == True + cartridge.write_battery(MAPPED_CONTENT) + assert cartridge.has_battery() == True print cartridge.batteryFile assert cartridge.batteryFile.read() == CONTENT - assert cartridge.readBattery() == MAPPED_CONTENT + assert cartridge.read_battery() == MAPPED_CONTENT - cartridge.removeBattery() - assert cartridge.hasBattery() == False + cartridge.remove_battery() + assert cartridge.has_battery() == False Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cpu.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cpu.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cpu.py Thu May 8 13:54:14 2008 @@ -20,7 +20,7 @@ def get_cpu(new=False): if new: cpu = CPU(Interrupt(), Memory()) - cpu.setROM([0]*0xFFFF); + cpu.set_rom([0]*0xFFFF); return cpu global TEST_CPU if TEST_CPU == None: @@ -91,20 +91,20 @@ assert cpu.read(address) == value -def test_relativeConditionalJump(): +def test_relative_conditional_jump(): cpu = get_cpu() pc = cpu.pc.get() value = 0x12 cpu.rom[constants.RESET_PC] = value # test jr_nn startCycles = cpu.cycles - cpu.relativeConditionalJump(True) + cpu.relative_conditional_jump(True) assert startCycles-cpu.cycles == 3 assert_registers(cpu, pc=pc+value+1) # test pc.inc startCycles = cpu.cycles pc = cpu.pc.get() - cpu.relativeConditionalJump(False) + cpu.relative_conditional_jump(False) assert startCycles-cpu.cycles == 2 assert cpu.pc.get() == pc+1 @@ -112,28 +112,28 @@ def test_flags(): cpu = get_cpu() cpu.f.set(constants.Z_FLAG) - assert cpu.isZ() == True - assert cpu.isNotZ() == False + assert cpu.is_z() == True + assert cpu.is_not_z() == False cpu.f.set(~constants.Z_FLAG) - assert cpu.isZ() == False - assert cpu.isNotZ() == True + assert cpu.is_z() == False + assert cpu.is_not_z() == True cpu.f.set(constants.C_FLAG) - assert cpu.isC() == True - assert cpu.isNotC() == False + assert cpu.is_c() == True + assert cpu.is_not_c() == False cpu.f.set(~constants.C_FLAG) - assert cpu.isC() == False - assert cpu.isNotC() == True + assert cpu.is_c() == False + assert cpu.is_not_c() == True def test_flags_memory_access(): cpu = get_cpu() cpu.f.set(constants.Z_FLAG) - assert cpu.isZ() == True + assert cpu.is_z() == True prepare_for_fetch(cpu, 0x1234, 0x1234) cpu.memory.write(0x1234, 0x12) - assert cpu.isZ() == True + assert cpu.is_z() == True cpu.rom[0x1234] = 0x12 - assert cpu.isZ() == True + assert cpu.is_z() == True def fetch_execute_cycle_test(cpu, opCode, cycles=0): @@ -183,8 +183,8 @@ def test_create_register_op_codes(): start = 0x09 step = 0x10 - func = CPU.addHL - registers = [CPU.getBC]*128 + func = CPU.add_hl + registers = [CPU.get_bc]*128 table = [(start, step, func, registers)] list = create_register_op_codes(table) opCode = start @@ -308,8 +308,8 @@ cpu.sp.set(0x1234) cycle_test(cpu, 0x08, 5) assert_default_registers(cpu, pc=startPC+2, sp=0x1234) - assert cpu.memory.read(0xCDEF) == cpu.sp.getLo() - assert cpu.memory.read(0xCDEF+1) == cpu.sp.getHi() + assert cpu.memory.read(0xCDEF) == cpu.sp.get_lo() + assert cpu.memory.read(0xCDEF+1) == cpu.sp.get_hi() # stop def test_0x10(): @@ -358,8 +358,8 @@ for index in range(0, len(registers)): prepare_for_fetch(cpu, value, value+1) cycle_test(cpu, opCode, 3) - assert registers[index].getLo() == value+1 - assert registers[index].getHi() == value + assert registers[index].get_lo() == value+1 + assert registers[index].get_hi() == value value += 3 opCode += 0x10 @@ -774,13 +774,13 @@ cpu.a.set(0) cpu.b.set(0) - cpu.addA(cpu.b.get, cpu.b.set) + cpu.add_a(cpu.b.get, cpu.b.set) assert_default_flags(cpu, zFlag=True, hFlag=False) cpu.reset() cpu.a.set(0x0F) cpu.b.set(0x01) - cpu.addA(cpu.b.get, cpu.b.set) + cpu.add_a(cpu.b.get, cpu.b.set) assert_default_flags(cpu, zFlag=False, hFlag=True) @@ -815,7 +815,7 @@ cpu.reset() a.set(0) b.set(0) - cpu.addWithCarry(b.get, b.set) + cpu.add_with_carry(b.get, b.set) assert_default_registers(cpu, a=0, f=None) assert_default_flags(cpu, zFlag=True, cFlag=False, hFlag=False) @@ -823,14 +823,14 @@ a.set(0) b.set(0) cpu.f.cFlag = True - cpu.addWithCarry(b.get, b.set) + cpu.add_with_carry(b.get, b.set) assert_default_registers(cpu, a=1, f=None) assert_default_flags(cpu, zFlag=False, cFlag=False, hFlag=False) cpu.reset() a.set(0xF0) b.set(0xFF) - cpu.addWithCarry(b.get, b.set) + cpu.add_with_carry(b.get, b.set) # overflow for a assert_default_registers(cpu, a=0xEF, bc=None, f=None) assert_default_flags(cpu, zFlag=False, cFlag=True, hFlag=False) @@ -838,7 +838,7 @@ cpu.reset() a.set(0x0F) b.set(0x01) - cpu.addWithCarry(b.get, b.set) + cpu.add_with_carry(b.get, b.set) assert_default_registers(cpu, a=0x10, f=None, bc=None) assert_default_flags(cpu, zFlag=False, cFlag=False, hFlag=True) @@ -901,7 +901,7 @@ cpu.reset() a.set(value) b.set(value) - cpu.subtractWithCarry(b.get, b.set) + cpu.subtract_with_carry(b.get, b.set) assert_default_registers(cpu, a=0, bc=None, f=None) assert_default_flags(cpu, zFlag=True, cFlag=False, hFlag=False, nFlag=True) @@ -909,14 +909,14 @@ a.set(value) b.set(value-1) cpu.f.cFlag = True - cpu.subtractWithCarry(b.get, b.set) + cpu.subtract_with_carry(b.get, b.set) assert_default_registers(cpu, a=0, bc=None, f=None) assert_default_flags(cpu, zFlag=True, cFlag=False, hFlag=False, nFlag=True) cpu.reset() a.set(0x20) b.set(0x01) - cpu.subtractWithCarry(b.get, b.set) + cpu.subtract_with_carry(b.get, b.set) # overflow for a assert_default_registers(cpu, a=0x1F, bc=None, f=None) assert_default_flags(cpu, zFlag=False, cFlag=False, hFlag=True, nFlag=True) @@ -1080,19 +1080,19 @@ value = 0x12 cpu.a.set(value) cpu.b.set(value) - cpu.compareA(cpu.b.get, cpu.b.set) + cpu.compare_a(cpu.b.get, cpu.b.set) assert_default_flags(cpu, zFlag=True, nFlag=True) cpu.reset() cpu.a.set(value) cpu.b.set(0) - cpu.compareA(cpu.b.get, cpu.b.set) + cpu.compare_a(cpu.b.get, cpu.b.set) assert_default_flags(cpu, zFlag=False, nFlag=True) cpu.reset() cpu.a.set(0xF0) cpu.b.set(0x01) - cpu.compareA(cpu.b.get, cpu.b.set) + cpu.compare_a(cpu.b.get, cpu.b.set) assert_default_flags(cpu, zFlag=False, hFlag=True, nFlag=True) @@ -1250,16 +1250,16 @@ cpu = get_cpu() cpu.halted = True cpu.cycles = 0xFF - cpu.handlePendingInterrupt() + cpu.handle_pending_interrupt() assert cpu.cycles == 0 cpu.reset() cpu.halted = True - cpu.interrupt.setInterruptEnable() - cpu.interrupt.vBlank.setPending() - assert cpu.interrupt.isPending() == True + cpu.interrupt.set_interrupt_enable() + cpu.interrupt.vBlank.set_pending() + assert cpu.interrupt.is_pending() == True cpu.cycles = 4 - cpu.handlePendingInterrupt() + cpu.handle_pending_interrupt() assert cpu.cycles == 0 assert cpu.halted == False @@ -1269,12 +1269,12 @@ cpu.pc.set(0x1234) cpu.sp.set(0x02) sp = cpu.sp.get() - cpu.interrupt.setInterruptEnable() - cpu.interrupt.vBlank.setPending() - cpu.interrupt.lcd.setPending() - assert cpu.interrupt.isPending() == True + cpu.interrupt.set_interrupt_enable() + cpu.interrupt.vBlank.set_pending() + cpu.interrupt.lcd.set_pending() + assert cpu.interrupt.is_pending() == True cpu.cycles = 0 - cpu.handlePendingInterrupt() + cpu.handle_pending_interrupt() assert cpu.cycles == 0 assert cpu.halted == False assert_default_registers(cpu, pc=cpu.interrupt.vBlank.callCode, sp=sp-2) @@ -1371,15 +1371,15 @@ cpu.ime = True cpu.halted = False prepare_for_fetch(cpu, 0x00) # nop 1 cycle - cpu.interrupt.vBlank.setPending() - cpu.interrupt.serial.setPending() - cpu.interrupt.setInterruptEnable(True) - assert cpu.interrupt.isPending() == True + cpu.interrupt.vBlank.set_pending() + cpu.interrupt.serial.set_pending() + cpu.interrupt.set_interrupt_enable(True) + assert cpu.interrupt.is_pending() == True assert cpu.halted == False assert cpu.ime == True cycle_test(cpu, 0xFB, 1+1) - assert cpu.interrupt.isPending() == False - assert cpu.interrupt.vBlank.isPending() == False + assert cpu.interrupt.is_pending() == False + assert cpu.interrupt.vBlank.is_pending() == False assert cpu.pc.get() == cpu.interrupt.vBlank.callCode assert cpu.ime == False @@ -1538,13 +1538,13 @@ cpu = get_cpu() a = cpu.a a.set(0x01) - cpu.rotateLeftA() + cpu.rotate_left_a() assert_default_flags(cpu, zFlag=False, cFlag=False) assert_default_registers(cpu, a=0x02, f=None) cpu.reset() a.set(0x40) - cpu.rotateLeftA() + cpu.rotate_left_a() assert_default_flags(cpu, zFlag=False, cFlag=True) assert_default_registers(cpu, a=0x80, f=None) Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_interrupt.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_interrupt.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_interrupt.py Thu May 8 13:54:14 2008 @@ -10,20 +10,20 @@ def test_reset(): interrupt = get_interrupt() assert interrupt.enable == 0 - assert interrupt.getInterruptFlag() == 0xE0 | constants.VBLANK + assert interrupt.get_interrupt_flag() == 0xE0 | constants.VBLANK interrupt.enable = 1 interrupt.flag = ~constants.VBLANK interrupt.reset() assert interrupt.enable == 0 - assert interrupt.getInterruptFlag() == 0xE0 | constants.VBLANK + assert interrupt.get_interrupt_flag() == 0xE0 | constants.VBLANK def test_is_pending(): interrupt = get_interrupt() - assert interrupt.isPending() == False - assert interrupt.isPending(0x00) == False - interrupt.setInterruptEnable(True) - assert interrupt.isPending() + assert interrupt.is_pending() == False + assert interrupt.is_pending(0x00) == False + interrupt.set_interrupt_enable(True) + assert interrupt.is_pending() def test_is_pending_common_masks(): @@ -31,23 +31,23 @@ for flag in interrupt.interruptFlags: interrupt.reset() interrupt.enable = True - assert interrupt.vBlank.isPending() - flag.setPending(True) - assert interrupt.isPending(flag.mask) + assert interrupt.vBlank.is_pending() + flag.set_pending(True) + assert interrupt.is_pending(flag.mask) def test_raise_lower_interrupt(): interrupt = get_interrupt() masks= [constants.LCD, constants.TIMER, constants.JOYPAD, constants.SERIAL] - interrupt.setInterruptEnable(True) - interrupt.vBlank.setPending(True) + interrupt.set_interrupt_enable(True) + interrupt.vBlank.set_pending(True) for mask in masks: - interrupt.raiseInterrupt(mask) - assert interrupt.maskMapping[mask].isPending() == True - assert interrupt.isPending(mask) == True + interrupt.raise_interrupt(mask) + assert interrupt.maskMapping[mask].is_pending() == True + assert interrupt.is_pending(mask) == True interrupt.lower(mask) - assert interrupt.isPending(mask) == False + assert interrupt.is_pending(mask) == False def test_read_write(): interrupt = get_interrupt() @@ -59,5 +59,5 @@ interrupt.reset() value = constants.LCD interrupt.write(constants.IF, value) - assert interrupt.getInterruptFlag() == 0xE0 | value + assert interrupt.get_interrupt_flag() == 0xE0 | value assert interrupt.read(constants.IF) == 0xE0 | value Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_joypad.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_joypad.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_joypad.py Thu May 8 13:54:14 2008 @@ -48,7 +48,7 @@ button = Button(value) assert button.oppositeButton == None assert button.codeValue == value - assert button.isPressed() == False + assert button.is_pressed() == False button2 = Button(value, button) assert button2.oppositeButton == button @@ -56,36 +56,36 @@ def test_getCode(): button = get_button() - assert button.getCode() == 0 + assert button.get_code() == 0 button.press() - assert button.getCode() == button.codeValue + assert button.get_code() == button.codeValue def test_press_release(): button = get_button() button2 = get_button() button.oppositeButton = button2; button2.press() - assert button2.isPressed() == True + assert button2.is_pressed() == True button.press() - assert button.isPressed() == True - assert button2.isPressed() == False + assert button.is_pressed() == True + assert button2.is_pressed() == False button.release() - assert button.isPressed() == False - assert button2.isPressed() == False + assert button.is_pressed() == False + assert button2.is_pressed() == False # TEST JOYPAD DRIVER ----------------------------------------------------------- def test_ini(): driver = get_driver() assert driver.raised == False - assert driver.getButtonCode() == 0 - assert driver.getDirectionCode() == 0 + assert driver.get_button_code() == 0 + assert driver.get_direction_code() == 0 def test_isRaised(): driver = get_driver() driver.raised = True assert driver.raised == True - assert driver.isRaised() == True + assert driver.is_raised() == True assert driver.raised == False def test_button_code_values(): @@ -102,10 +102,10 @@ def test_toggle_opposite_directions(): driver = get_driver() - directions = [(driver.buttonUp, driver.up, driver.down), - (driver.buttonDown, driver.down, driver.up), - (driver.buttonLeft, driver.left, driver.right), - (driver.buttonRight, driver.right, driver.left)] + directions = [(driver.button_up, driver.up, driver.down), + (driver.button_down, driver.down, driver.up), + (driver.button_left, driver.left, driver.right), + (driver.button_right, driver.right, driver.left)] for dir in directions: toggleFunction = dir[0] button = dir[1] @@ -114,70 +114,70 @@ oppositeButton.press() assert driver.raised == False - assert button.isPressed() == False - assert oppositeButton.isPressed() == True - assert driver.getDirectionCode() == oppositeButton.codeValue - assert driver.getButtonCode() == 0 + assert button.is_pressed() == False + assert oppositeButton.is_pressed() == True + assert driver.get_direction_code() == oppositeButton.codeValue + assert driver.get_button_code() == 0 toggleFunction() assert driver.raised == True - assert button.isPressed() == True - assert oppositeButton.isPressed() == False - assert driver.getDirectionCode() == button.codeValue - assert driver.getButtonCode() == 0 + assert button.is_pressed() == True + assert oppositeButton.is_pressed() == False + assert driver.get_direction_code() == button.codeValue + assert driver.get_button_code() == 0 toggleFunction(False) - assert button.isPressed() == False - assert oppositeButton.isPressed() == False - assert driver.getDirectionCode() == 0 - assert driver.getButtonCode() == 0 + assert button.is_pressed() == False + assert oppositeButton.is_pressed() == False + assert driver.get_direction_code() == 0 + assert driver.get_button_code() == 0 def test_toggle_buttons(): driver = get_driver() - buttons = [(driver.buttonSelect, driver.select), - (driver.buttonStart, driver.start), - (driver.buttonA, driver.a), - (driver.buttonB, driver.b)] + buttons = [(driver.button_select, driver.select), + (driver.button_start, driver.start), + (driver.button_a, driver.a), + (driver.button_b, driver.b)] for button in buttons: toggleFunction = button[0] button = button[1] driver.reset() - assert button.isPressed() == False - assert driver.getButtonCode() == 0 - assert driver.getDirectionCode() == 0 + assert button.is_pressed() == False + assert driver.get_button_code() == 0 + assert driver.get_direction_code() == 0 toggleFunction() assert driver.raised == True - assert button.isPressed() == True - assert driver.getButtonCode() == button.codeValue - assert driver.getDirectionCode() == 0 + assert button.is_pressed() == True + assert driver.get_button_code() == button.codeValue + assert driver.get_direction_code() == 0 toggleFunction(False) - assert button.isPressed() == False - assert driver.getButtonCode() == 0 - assert driver.getDirectionCode() == 0 + assert button.is_pressed() == False + assert driver.get_button_code() == 0 + assert driver.get_direction_code() == 0 def test_toggle_multiple_buttons(): driver = get_driver() - buttons = [(driver.buttonSelect, driver.select), - (driver.buttonStart, driver.start), - (driver.buttonA, driver.a), - (driver.buttonB, driver.b)] - toggle_multiple_test(driver, driver.getButtonCode, buttons) + buttons = [(driver.button_select, driver.select), + (driver.button_start, driver.start), + (driver.button_a, driver.a), + (driver.button_b, driver.b)] + toggle_multiple_test(driver, driver.get_button_code, buttons) def test_toggle_mutliple_directions(): """ only testing non-opposite buttons, since they would exclude each other """ driver = get_driver() - directions = [(driver.buttonUp, driver.up), - #(driver.buttonDown, driver.down), - #(driver.buttonLeft, driver.left), - (driver.buttonRight, driver.right)] - toggle_multiple_test(driver, driver.getDirectionCode, directions) + directions = [(driver.button_up, driver.up), + #(driver.button_down, driver.down), + #(driver.button_left, driver.left), + (driver.button_right, driver.right)] + toggle_multiple_test(driver, driver.get_direction_code, directions) def toggle_multiple_test(driver, codeGetter, buttons): size = len(buttons) @@ -190,7 +190,7 @@ code |= buttons[j][1].codeValue else: buttons[j][0](False) - assert buttons[j][1].isPressed() == toggled[j] + assert buttons[j][1].is_pressed() == toggled[j] assert codeGetter() == code @@ -246,10 +246,10 @@ def test_update(): joypad = get_joypad() - joypad.driver.buttonSelect() - assert joypad.driver.getButtonCode() == constants.BUTTON_SELECT - joypad.driver.buttonUp() - assert joypad.driver.getDirectionCode() == constants.BUTTON_UP + joypad.driver.button_select() + assert joypad.driver.get_button_code() == constants.BUTTON_SELECT + joypad.driver.button_up() + assert joypad.driver.get_direction_code() == constants.BUTTON_UP assert joypad.buttonCode == 0xF joypad.joyp = 0x1 joypad.update() Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_register.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_register.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_register.py Thu May 8 13:54:14 2008 @@ -19,7 +19,7 @@ def get_cpu(new=False): if new: cpu = CPU(Interrupt(), Memory()) - cpu.setROM([0]*0xFFFF); + cpu.set_rom([0]*0xFFFF); return cpu global TEST_CPU if TEST_CPU == None: @@ -65,8 +65,8 @@ cpu = get_cpu() register = DoubleRegister(cpu) assert register.get() == 0 - assert register.getHi() == 0 - assert register.getLo() == 0 + assert register.get_hi() == 0 + assert register.get_lo() == 0 value = 0x1234 reg1 = Register(cpu) reg1.set(0x12) @@ -75,8 +75,8 @@ register = DoubleRegister(cpu, reg1, reg2) assert register.hi == reg1 assert register.lo == reg2 - assert register.getHi() == reg1.get() - assert register.getLo() == reg2.get() + assert register.get_hi() == reg1.get() + assert register.get_lo() == reg2.get() def test_double_register(): register = DoubleRegister(get_cpu()) @@ -102,23 +102,23 @@ oldCycles = register.cpu.cycles register.set(valueHi, valueLo) assert oldCycles-register.cpu.cycles == 2 - assert register.getHi() == valueHi - assert register.getLo() == valueLo + assert register.get_hi() == valueHi + assert register.get_lo() == valueLo assert register.get() == value valueHi = 0x56 oldCycles = register.cpu.cycles - register.setHi(valueHi) + register.set_hi(valueHi) assert oldCycles-register.cpu.cycles == 1 - assert register.getHi() == valueHi - assert register.getLo() == valueLo + assert register.get_hi() == valueHi + assert register.get_lo() == valueLo valueLo = 0x78 oldCycles = register.cpu.cycles - register.setLo(valueLo) + register.set_lo(valueLo) assert oldCycles-register.cpu.cycles == 1 - assert register.getHi() == valueHi - assert register.getLo() == valueLo + assert register.get_hi() == valueHi + assert register.get_lo() == valueLo def test_double_register_methods(): Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_rom.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_rom.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_rom.py Thu May 8 13:54:14 2008 @@ -15,7 +15,7 @@ def test_rom1(): gameBoy = GameBoy() try: - gameBoy.loadCartridgeFile(ROM_PATH+"/rom1/rom1.raw") + gameBoy.load_cartridge_file(ROM_PATH+"/rom1/rom1.raw") py.test.fail() except: pass @@ -24,7 +24,7 @@ def test_rom2(): gameBoy = GameBoy() try: - gameBoy.loadCartridgeFile(ROM_PATH+"/rom2/rom2.raw") + gameBoy.load_cartridge_file(ROM_PATH+"/rom2/rom2.raw") py.test.fail() except: pass @@ -33,13 +33,13 @@ def test_rom3(): """ some NOP and an endless loop at the end '""" gameBoy = GameBoy() - gameBoy.loadCartridgeFile(ROM_PATH+"/rom3/rom3.gb") + gameBoy.load_cartridge_file(ROM_PATH+"/rom3/rom3.gb") gameBoy.emulate(EMULATION_CYCLES) def test_rom4(): gameBoy = GameBoy() - gameBoy.loadCartridgeFile(ROM_PATH+"/rom4/rom4.gb") + gameBoy.load_cartridge_file(ROM_PATH+"/rom4/rom4.gb") gameBoy.emulate(EMULATION_CYCLES) assert gameBoy.cpu.ime == False @@ -49,7 +49,7 @@ def test_rom5(): gameBoy = GameBoy() - gameBoy.loadCartridgeFile(ROM_PATH+"/rom5/rom5.gb") + gameBoy.load_cartridge_file(ROM_PATH+"/rom5/rom5.gb") gameBoy.emulate(EMULATION_CYCLES) # stop test assert gameBoy.cpu.a.get() != 0xFF @@ -57,24 +57,24 @@ def test_rom6(): gameBoy = GameBoy() - gameBoy.loadCartridgeFile(ROM_PATH+"/rom6/rom6.gb") + gameBoy.load_cartridge_file(ROM_PATH+"/rom6/rom6.gb") gameBoy.emulate(EMULATION_CYCLES) def test_rom7(): gameBoy = GameBoy() - gameBoy.loadCartridgeFile(ROM_PATH+"/rom7/rom7.gb") + gameBoy.load_cartridge_file(ROM_PATH+"/rom7/rom7.gb") gameBoy.emulate(EMULATION_CYCLES) def test_rom8(): gameBoy = GameBoy() - gameBoy.loadCartridgeFile(ROM_PATH+"/rom8/rom8.gb") + gameBoy.load_cartridge_file(ROM_PATH+"/rom8/rom8.gb") gameBoy.emulate(EMULATION_CYCLES) def test_rom9(): gameBoy = GameBoy() - gameBoy.loadCartridgeFile(ROM_PATH+"/rom9/rom9.gb") + gameBoy.load_cartridge_file(ROM_PATH+"/rom9/rom9.gb") gameBoy.emulate(EMULATION_CYCLES) Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_serial.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_serial.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_serial.py Thu May 8 13:54:14 2008 @@ -18,11 +18,11 @@ assert serial.sc == 0 -def test_setSerialControl(): +def test_set_serial_control(): serial = get_serial() value = 0x12 - serial.setSerialControl(value) - assert serial.getSerialControl() == value + serial.set_serial_control(value) + assert serial.get_serial_control() == value assert serial.cycles == constants.SERIAL_IDLE_CLOCK + constants.SERIAL_CLOCK @@ -43,7 +43,7 @@ assert cycles-serial.cycles == 2 assert serial.sb == 0 assert serial.sc == 0x81 - assert serial.interrupt.serial.isPending() == False + assert serial.interrupt.serial.is_pending() == False serial.reset() serial.sc = 0x81 @@ -52,7 +52,7 @@ assert serial.sb == 0xFF assert serial.sc == 0x81 & 0x7F assert serial.cycles == constants.SERIAL_IDLE_CLOCK - assert serial.interrupt.serial.isPending() == True + assert serial.interrupt.serial.is_pending() == True def test_read_write(): @@ -67,4 +67,5 @@ assert serial.read(constants.SC) == value assert serial.sc == value - assert serial.read(0) == 0xFF \ No newline at end of file + assert serial.read(0) == 0xFF + \ No newline at end of file Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_timer.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_timer.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_timer.py Thu May 8 13:54:14 2008 @@ -28,32 +28,32 @@ timer.div = 10 value = 0x11 timer.write(constants.DIV, value) - assert timer.getDivider() == 0 + assert timer.get_divider() == 0 assert timer.read(constants.DIV) == 0 timer.reset() timer.write(constants.TIMA, value) - assert timer.getTimerCounter() == value + assert timer.get_timer_counter() == value assert timer.read(constants.TIMA) == value timer.reset() timer.write(constants.TMA, value) - assert timer.getTimerModulo() == value + assert timer.get_timer_modulo() == value assert timer.read(constants.TMA) == value timer.reset() -def test_getTimerControl(): +def test_get_timer_control(): timer = get_timer() value = 0x12 timer.write(constants.TAC, value) - assert timer.getTimerControl() == 0xF8 | value + assert timer.get_timer_control() == 0xF8 | value assert timer.read(constants.TAC) == 0xF8 |value -def test_setTimerControl(): +def test_set_timer_control(): timer = get_timer() value = 0x12 - timer.setTimerControl(value) + timer.set_timer_control(value) assert timer.tac == value assert timer.timerCycles == constants.TIMER_CLOCK[value & 0x03] assert timer.timerClock == constants.TIMER_CLOCK[value & 0x03] @@ -61,7 +61,7 @@ timer.tac = value+1 timer.timerClock = 0 timer.timerCycles = 0 - timer.setTimerControl(value+1) + timer.set_timer_control(value+1) assert timer.tac == value+1 assert timer.timerClock == 0 assert timer.timerClock == 0 @@ -70,66 +70,66 @@ timer = get_timer() value = 0x12 timer.div = value - assert timer.getDivider() == timer.div + assert timer.get_divider() == timer.div # divider resets on write - timer.setDivider(value) - assert timer.getDivider() == 0 + timer.set_divider(value) + assert timer.get_divider() == 0 def test_cycles(): timer = get_timer() value = 10 timer.dividerCycles = value - assert timer.getCycles() == timer.dividerCycles + assert timer.get_cycles() == timer.dividerCycles timer.tac = 0x04 timer.timerCycles = value-1 timer.timerCycles = value - assert timer.getCycles() == timer.timerCycles + assert timer.get_cycles() == timer.timerCycles def test_emulateDivider_normal(): timer = get_timer() value = 2 timer.timerCycles = 0 - timer.emulateTimer(value) + timer.emulate_timer(value) def test_test_emulateDivider_zero(): timer = get_timer() value = 2 timer.timerCycles = value - timer.emulateTimer(value) + timer.emulate_timer(value) assert timer.timerCycles == value -def test_emulateTimer_tac_return(): +def test_emulate_timer_tac_return(): timer = get_timer() timer.tac = 0 timer.timerCycles = -10 cycles = timer.timerCycles - timer.emulateTimer(10) + timer.emulate_timer(10) assert timer.timerCycles == cycles -def test_emulateTimer_timer_cycles_return(): +def test_emulate_timer_timer_cycles_return(): timer = get_timer() timer.tac = 0x04 value = 10 timer.timerCycles = value+1 cycles = timer.timerCycles - timer.emulateTimer(value) + timer.emulate_timer(value) assert timer.timerCycles == 1 timer = get_timer() timer.tac = 0x04 -def test_emulateTimer_interrupt(): +def test_emulate_timer_interrupt(): timer = get_timer() ticks = 0 timer.tac = 0x04 timer.tima = -1 # raise an interupt as we pass 0 - assert timer.interrupt.isPending(constants.TIMER) == False + assert timer.interrupt.is_pending(constants.TIMER) == False timer.timerCycles = -timer.timerClock+1 - timer.emulateTimer(ticks) + timer.emulate_timer(ticks) assert timer.timerCycles == 1 assert timer.tima == timer.tma - assert timer.interrupt.timer.isPending() + assert timer.interrupt.timer.is_pending() \ No newline at end of file Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/timer.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/timer.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/timer.py Thu May 8 13:54:14 2008 @@ -3,6 +3,7 @@ Timer and Divider """ + from pypy.lang.gameboy import constants from math import ceil @@ -20,61 +21,61 @@ def write(self, address, data): if address==constants.DIV: - self.setDivider(data) + self.set_divider(data) elif address==constants.TIMA: - self.setTimerCounter(data) + self.set_timer_counter(data) elif address==constants.TMA: - self.setTimerModulo(data) + self.set_timer_modulo(data) elif address==constants.TAC: - self.setTimerControl(data) + self.set_timer_control(data) def read(self, address): if address==constants.DIV: - return self.getDivider() + return self.get_divider() elif address==constants.TIMA: - return self.getTimerCounter() + return self.get_timer_counter() elif address==constants.TMA: - return self.getTimerModulo() + return self.get_timer_modulo() elif address==constants.TAC: - return self.getTimerControl() + return self.get_timer_control() return 0xFF - def getDivider(self): + def get_divider(self): return self.div - def setDivider(self, data): #DIV register resets on write + def set_divider(self, data): #DIV register resets on write self.div = 0 - def getTimerCounter(self): + def get_timer_counter(self): return self.tima - def setTimerCounter(self, data): + def set_timer_counter(self, data): self.tima = data - def getTimerModulo(self): + def get_timer_modulo(self): return self.tma - def setTimerModulo(self, data): + def set_timer_modulo(self, data): self.tma = data - def getTimerControl(self): + def get_timer_control(self): return 0xF8 | self.tac - def setTimerControl(self, data): + def set_timer_control(self, data): if ((self.tac & 0x03) != (data & 0x03)): self.timerClock = self.timerCycles = constants.TIMER_CLOCK[data & 0x03] self.tac = data - def getCycles(self): + def get_cycles(self): if (self.tac & 0x04) != 0 and self.timerCycles < self.dividerCycles: return self.timerCycles return self.dividerCycles def emulate(self, ticks): - self.emulateDivider(ticks) - self.emulateTimer(ticks) + self.emulate_divider(ticks) + self.emulate_timer(ticks) - def emulateDivider(self, ticks): + def emulate_divider(self, ticks): self.dividerCycles -= ticks if self.dividerCycles > 0: return @@ -82,23 +83,23 @@ self.div = (self.div + count) & 0xFF self.dividerCycles += constants.DIV_CLOCK*count - def emulateTimer(self, ticks): + def emulate_timer(self, ticks): if (self.tac & 0x04) == 0: return self.timerCycles -= ticks if self.timerCycles > 0: return count = int(ceil(-1.0*self.timerCycles / self.timerClock)) - self.timaZeroPassCheck(count) + self.tima_tero_pass_check(count) self.tima = (self.tima + count) & 0xFF self.timerCycles += self.timerClock * count - def timaZeroPassCheck(self, count): + def tima_tero_pass_check(self, count): if (self.tima < 0) and (self.tima + count >= 0): self.tima = self.tma - count print "raising" - self.interrupt.raiseInterrupt(constants.TIMER) - print self.interrupt.timer.isPending(), self.interrupt.isPending(constants.TIMER) + self.interrupt.raise_interrupt(constants.TIMER) + print self.interrupt.timer.is_pending(), self.interrupt.is_pending(constants.TIMER) # CLOCK DRIVER ----------------------------------------------------------------- @@ -107,6 +108,6 @@ def __init__(self): pass - def getTime(self): + def get_time(self): return System.currentTimeMillis() / 1000 Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/video.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/video.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/video.py Thu May 8 13:54:14 2008 @@ -15,17 +15,16 @@ #objects = []#= new int[OBJECTS_PER_LINE] #palette = []#= new int[1024] - def __init__(self, videoDriver, interrupt, memory): self.driver = videoDriver self.interrupt = interrupt self.memory = memory self.reset() - def getFrameSkip(self): + def get_frame_skip(self): return self.frameSkip - def setFrameSkip(self, frameSkip): + def set_frame_skip(self, frameSkip): self.frameSkip = frameSkip def reset(self): @@ -61,213 +60,217 @@ def write(self, address, data): # assert data >= 0x00 and data <= 0xFF if address == constants.LCDC : - self.setControl(data) + self.set_control(data) elif address == constants.STAT: - self.setStatus(data) + self.set_status(data) elif address == constants.SCY: - self.setScrollY(data) + self.set_scroll_y(data) elif address == constants.SCX: - self.setScrollX(data) + self.set_scroll_x(data) elif address == constants.LY: # Read OnlineY pass elif address == constants.LYC: - self.setLYCompare(data) + self.set_ly_compare(data) elif address == constants.DMA: - self.setDMA(data) + self.set_dma(data) elif address == constants.BGP: - self.setBackgroundPalette(data) + self.set_background_palette(data) elif address == constants.OBP0: - self.setObjectPalette0(data) + self.set_object_palette_0(data) elif address == constants.OBP1: - self.setObjectPalette1(data) + self.set_object_palette_1(data) elif address == constants.WY: - self.setWindowY(data) + self.set_window_y(data) elif address == constants.WX: - self.setWindowX(data) + self.set_window_x(data) else: - self.writeOAM(address, data) + self.write_oam(address, data) - def writeOAM(self, address, data): - if (address >= constants.OAM_ADDR and address < constants.OAM_ADDR + constants.OAM_SIZE): + def write_oam(self, address, data): + if address >= constants.OAM_ADDR and \ + address < constants.OAM_ADDR + constants.OAM_SIZE: self.oam[address - constants.OAM_ADDR] = data & 0xFF - elif (address >= constants.VRAM_ADDR and address < constants.VRAM_ADDR + constants.VRAM_SIZE): - self.vram[address - constants.VRAM_ADDR] = data & 0xFF + elif address >= constants.VRAM_ADDR and \ + address < constants.VRAM_ADDR + constants.VRAM_SIZE: + self.vram[address - constants.VRAM_ADDR] = data & 0xFF def read(self, address): if address == constants.LCDC: - return self.getControl() + return self.get_control() elif address == constants.STAT: - return self.getStatus() + return self.get_status() elif address == constants.SCY: - return self.getScrollY() + return self.get_scroll_y() elif address == constants.SCX: - return self.getScrollX() + return self.get_scroll_x() elif address == constants.LY: - return self.getLineY() + return self.get_line_y() elif address == constants.LYC: - return self.getLineYCompare() + return self.get_line_y_compare() elif address == constants.DMA: - return self.getDMA() + return self.get_dma() elif address == constants.BGP: - return self.getBackgroundPalette() + return self.get_background_palette() elif address == constants.OBP0: - return self.getObjectPalette0() + return self.get_object_palette_0() elif address == constants.OBP1: - return self.getObjectPalette1() + return self.get_object_palette_1() elif address == constants.WY: - return self.getWindowY() + return self.get_window_y() elif address == constants.WX: - return self.getWindowX() + return self.get_window_x() else: - return self.readOAM(address) - + return self.read_oam(address) - def readOAM(self, address): - if (address >= constants.OAM_ADDR and address < constants.OAM_ADDR + constants.OAM_SIZE): - return self.oam[address - constants.OAM_ADDR] - elif (address >= constants.VRAM_ADDR and address < constants.VRAM_ADDR + constants.VRAM_SIZE): - return self.vram[address - constants.VRAM_ADDR] + def read_oam(self, address): + if (address >= constants.OAM_ADDR and \ + address < constants.OAM_ADDR + constants.OAM_SIZE): + return self.oam[address - constants.OAM_ADDR] + elif (address >= constants.VRAM_ADDR and \ + address < constants.VRAM_ADDR + constants.VRAM_SIZE): + return self.vram[address - constants.VRAM_ADDR] return 0xFF - def getCycles(self): + def get_cycles(self): return self.cycles def emulate(self, ticks): if (self.control & 0x80) != 0: self.cycles -= ticks - self.consumeCycles() + self.consume_cycles() - def consumeCycles(self): - while (self.cycles <= 0): + def consume_cycles(self): + while self.cycles <= 0: if self.stat == 0: - self.emulateHBlank() + self.emulate_hblank() elif self.stat == 1: - self.emulateVBlank() + self.emulate_vblank() elif self.stat == 2: - self.emulateOAM() + self.emulate_oam() else: - self.emulateTransfer() + self.emulate_transfer() - def getControl(self): + def get_control(self): return self.control - def setControl(self, data): + def set_control(self, data): if (self.control & 0x80) != (data & 0x80): - self.resetControl(data) + self.reset_control(data) # don't draw window if it was not enabled and not being drawn before - if ((self.control & 0x20) == 0 and (data & 0x20) != 0 and self.wlineY == 0 and self.lineY > self.windowY): - self.wlineY = 144 + if (self.control & 0x20) == 0 and (data & 0x20) != 0 and \ + self.wlineY == 0 and self.lineY > self.windowY: + self.wlineY = 144 self.control = data - def resetControl(self, data): - # NOTE: do not reset constants.LY=LYC flag (bit 2) of the STAT register (Mr. Do!) - if (data & 0x80) != 0: - self.stat = (self.stat & 0xFC) | 0x02 - self.cycles = constants.MODE_2_TICKS - self.lineY = 0 - self.display = False - else: - self.stat = (self.stat & 0xFC) | 0x00 - self.cycles = constants.MODE_1_TICKS - self.lineY = 0 - self.clearFrame() + def reset_control(self, data): + # NOTE: do not reset constants.LY=LYC flag (bit 2) of the STAT register (Mr. Do!) + if (data & 0x80) != 0: + self.stat = (self.stat & 0xFC) | 0x02 + self.cycles = constants.MODE_2_TICKS + self.lineY = 0 + self.display = False + else: + self.stat = (self.stat & 0xFC) | 0x00 + self.cycles = constants.MODE_1_TICKS + self.lineY = 0 + self.clear_frame() - def getStatus(self): + def get_status(self): return 0x80 | self.stat - def setStatus(self, data): + def set_status(self, data): self.stat = (self.stat & 0x87) | (data & 0x78) # Gameboy Bug - if ((self.control & 0x80) != 0 and (self.stat & 0x03) == 0x01 and (self.stat & 0x44) != 0x44): - self.interrupt.raiseInterrupt(constants.LCD) + if (self.control & 0x80) != 0 and (self.stat & 0x03) == 0x01 and \ + (self.stat & 0x44) != 0x44: + self.interrupt.raise_interrupt(constants.LCD) - def getScrollY(self): + def get_scroll_y(self): return self.scrollY - def setScrollY(self, data): + def set_scroll_y(self, data): self.scrollY = data - def getScrollX(self): + def get_scroll_x(self): return self.scrollX - def setScrollX(self, data): + def set_scroll_x(self, data): self.scrollX = data - def getLineY(self): + def get_line_y(self): return self.lineY - def getLineYCompare(self): + def get_line_y_compare(self): return self.lineYCompare - def setLYCompare(self, data): + def set_ly_compare(self, data): self.lineYCompare = data if (self.control & 0x80) == 0: return - if (self.lineY == self.lineYCompare): + if self.lineY == self.lineYCompare: # NOTE: raise interrupt once per line if (self.stat & 0x04) == 0: # constants.LYC=LY interrupt self.stat |= 0x04 # if (self.stat & 0x40) != 0: - self.interrupt.raiseInterrupt(constants.LCD) + self.interrupt.raise_interrupt(constants.LCD) else: self.stat &= 0xFB - def getDMA(self): + def get_dma(self): return self.dma - def setDMA(self, data): + def set_dma(self, data): self.dma = data for index in range(0, constants.OAM_SIZE): self.oam[index] = self.memory.read((self.dma << 8) + index) - - def getBackgroundPalette(self): + def get_background_palette(self): return self.backgroundPalette - def setBackgroundPalette(self, data): - if (self.backgroundPalette != data): + def set_background_palette(self, data): + if self.backgroundPalette != data: self.backgroundPalette = data self.dirty = True - def getObjectPalette0(self): + def get_object_palette_0(self): return self.objectPalette0 - def setObjectPalette0(self, data): - if (self.objectPalette0 != data): + def set_object_palette_0(self, data): + if self.objectPalette0 != data: self.objectPalette0 = data self.dirty = True - def getObjectPalette1(self): + def get_object_palette_1(self): return self.objectPalette1 - def setObjectPalette1(self, data): - if (self.objectPalette1 != data): + def set_object_palette_1(self, data): + if self.objectPalette1 != data: self.objectPalette1 = data self.dirty = True - def getWindowY(self): + def get_window_y(self): return self.windowY - def setWindowY(self, data): + def set_window_y(self, data): self.windowY = data - def getWindowX(self): + def get_window_x(self): return self.windowX - def setWindowX(self, data): + def set_window_x(self, data): self.windowX = data - def emulateOAM(self): + def emulate_oam(self): self.stat = (self.stat & 0xFC) | 0x03 self.cycles += constants.MODE_3_BEGIN_TICKS self.transfer = True - def emulateTransfer(self): + def emulate_transfer(self): if self.transfer: - if (self.display): - self.drawLine() + if self.display: + self.draw_line() self.stat = (self.stat & 0xFC) | 0x03 self.cycles += constants.MODE_3_END_TICKS self.transfer = False @@ -275,34 +278,34 @@ self.stat = (self.stat & 0xFC) self.cycles += constants.MODE_0_TICKS # H-Blank interrupt - if ((self.stat & 0x08) != 0 and (self.stat & 0x44) != 0x44): - self.interrupt.raiseInterrupt(constants.LCD) + if (self.stat & 0x08) != 0 and (self.stat & 0x44) != 0x44: + self.interrupt.raise_interrupt(constants.LCD) - def emulateHBlank(self): + def emulate_hblank(self): self.lineY+=1 - self.emulateHBlankLineYCompare() + self.emulate_hblank_line_y_compare() if self.lineY < 144: - self.emulateHBlankPart1() + self.emulate_hblank_part_1() else: - self.emulateHBlankPart2() + self.emulate_hblank_part_2() - def emulateHBlankLineYCompare(self): + def emulate_hblank_line_y_compare(self): if self.lineY == self.lineYCompare: # constants.LYC=LY interrupt self.stat |= 0x04 if (self.stat & 0x40) != 0: - self.interrupt.raiseInterrupt(constants.LCD) + self.interrupt.raise_interrupt(constants.LCD) else: self.stat &= 0xFB - def emulateHBlankPart1(self): + def emulate_hblank_part_1(self): self.stat = (self.stat & 0xFC) | 0x02 self.cycles += constants.MODE_2_TICKS # constants.OAM interrupt - if ((self.stat & 0x20) != 0 and (self.stat & 0x44) != 0x44): - self.interrupt.raiseInterrupt(constants.LCD) + if (self.stat & 0x20) != 0 and (self.stat & 0x44) != 0x44: + self.interrupt.raise_interrupt(constants.LCD) - def emulateHBlankPart2(self): + def emulate_hblank_part_2(self): if self.display: self.drawFrame() self.frames += 1 @@ -316,37 +319,36 @@ self.cycles += constants.MODE_1_BEGIN_TICKS self.vblank = True - - def emulateVBlank(self): + def emulate_vblank(self): if self.vblank: - self.emulateVBlankVBlank() + self.emulate_vblank_vblank() elif self.lineY == 0: - self.emulateVBlankFirstYLine() + self.emulate_vblank_first_y_line() else: - self.emulateVBlankOther() + self.emulate_vblank_other() - def emulateVBlankVBlank(self): + def emulate_vblank_vblank(self): self.vblank = False self.stat = (self.stat & 0xFC) | 0x01 self.cycles += constants.MODE_1_TICKS - constants.MODE_1_BEGIN_TICKS # V-Blank interrupt - if ((self.stat & 0x10) != 0): - self.interrupt.raiseInterrupt(constants.LCD) + if (self.stat & 0x10) != 0: + self.interrupt.raise_interrupt(constants.LCD) # V-Blank interrupt - self.interrupt.raiseInterrupt(constants.VBLANK) + self.interrupt.raise_interrupt(constants.VBLANK) - def emulateVBlankFirstYLine(self): + def emulate_vblank_first_y_line(self): self.stat = (self.stat & 0xFC) | 0x02 self.cycles += constants.MODE_2_TICKS # constants.OAM interrupt - if ((self.stat & 0x20) != 0 and (self.stat & 0x44) != 0x44): - self.interrupt.raiseInterrupt(constants.LCD) + if (self.stat & 0x20) != 0 and (self.stat & 0x44) != 0x44: + self.interrupt.raise_interrupt(constants.LCD) - def emulateVBlankOther(self): - if (self.lineY < 153): + def emulate_vblank_other(self): + if self.lineY < 153: self.lineY+=1 self.stat = (self.stat & 0xFC) | 0x01 - if (self.lineY == 153): + if self.lineY == 153: self.cycles += constants.MODE_1_END_TICKS else: self.cycles += constants.MODE_1_TICKS @@ -354,37 +356,37 @@ self.lineY = self.wlineY = 0 self.stat = (self.stat & 0xFC) | 0x01 self.cycles += constants.MODE_1_TICKS - constants.MODE_1_END_TICKS - if (self.lineY == self.lineYCompare): + if self.lineY == self.lineYCompare: # constants.LYC=LY interrupt self.stat |= 0x04 - if ((self.stat & 0x40) != 0): - self.interrupt.raiseInterrupt(constants.LCD) + if (self.stat & 0x40) != 0: + self.interrupt.raise_interrupt(constants.LCD) else: self.stat &= 0xFB - def drawFrame(self): - self.driver.updateDisplay() + def draw_frame(self): + self.driver.update_display() - def clearFrame(self): - self.clearPixels() - self.driver.updateDisplay() + def clear_frame(self): + self.clear_pixels() + self.driver.update_display() - def drawLine(self): + def draw_line(self): if (self.control & 0x01) != 0: - self.drawBackground() + self.draw_background() else: - self.drawCleanBackground() + self.draw_clean_background() if (self.control & 0x20) != 0: - self.drawWindow() + self.draw_window() if (self.control & 0x02) != 0: - self.drawObjects() - self.drawPixels() + self.draw_objects() + self.draw_pixels() - def drawCleanBackground(self): + def draw_clean_background(self): for x in range(0, 8+160+8): self.line[x] = 0x00 - def drawBackground(self): + def draw_background(self): y = (self.scrollY + self.lineY) & 0xFF x = self.scrollX & 0xFF tileMap = constants.VRAM_MAP_A @@ -395,10 +397,11 @@ tileData = constants.VRAM_DATA_A tileMap += ((y >> 3) << 5) + (x >> 3) tileData += (y & 7) << 1 - self.drawTiles(8 - (x & 7), tileMap, tileData) + self.draw_tiles(8 - (x & 7), tileMap, tileData) - def drawWindow(self): - if (self.lineY < self.windowY or self.windowX >= 167 or self.wlineY >= 144): + def draw_window(self): + if self.lineY < self.windowY or self.windowX >= 167 or \ + self.wlineY >= 144: return tileMap = constants.VRAM_MAP_A if (self.control & 0x40) != 0: @@ -408,11 +411,11 @@ tileData = constants.VRAM_DATA_A tileMap += (self.wlineY >> 3) << 5 tileData += (self.wlineY & 7) << 1 - self.drawTiles(self.windowX + 1, tileMap, tileData) + self.draw_tiles(self.windowX + 1, tileMap, tileData) self.wlineY+=1 - def drawObjects(self): - count = self.scanObjects() + def draw_objects(self): + count = self.scan_objects() lastx = 176 for index in range(176, count): data = self.objects[index] @@ -420,12 +423,12 @@ flags = (data >> 12) & 0xFF address = data & 0xFFF if (x + 8 <= lastx): - self.drawObjectTile(x, address, flags) + self.draw_object_tile(x, address, flags) else: - self.drawOverlappedObjectTile(x, address, flags) + self.draw_overlapped_object_tile(x, address, flags) lastx = x - def scanObjects(self): + def scan_objects(self): count = 0 # search active objects for offset in range(0, 4*40, 4): @@ -453,42 +456,44 @@ # Y flip if ((flags & 0x40) != 0): y = 7 - y - self.objects[count] = (x << 24) + (count << 20) + (flags << 12) + ((tile << 4) + (y << 1)) + self.objects[count] = (x << 24) + (count << 20) + (flags << 12) + \ + (tile << 4) + (y << 1) count += 1 if count >= constants.OBJECTS_PER_LINE: break - self.sortScanObject(count) + self.sort_scan_object(count) return count - def sortScanObject(self, count): + def sort_scan_object(self, count): # sort objects from lower to higher priority for index in range(0, count): rightmost = index for number in range(index+1, count): - if (self.objects[number] >> 20) > (self.objects[rightmost] >> 20): + if (self.objects[number] >> 20) > \ + (self.objects[rightmost] >> 20): rightmost = number if rightmost != index: data = self.objects[index] self.objects[index] = self.objects[rightmost] self.objects[rightmost] = data - def drawTiles(self, x, tileMap, tileData): + def draw_tiles(self, x, tileMap, tileData): while (x < 168): if (self.control & 0x10) != 0: tile = self.vram[tileMap] & 0xFF else: tile = (self.vram[tileMap] ^ 0x80) & 0xFF - self.drawTile(x, tileData + (tile << 4)) + self.draw_tile(x, tileData + (tile << 4)) tileMap = (tileMap & 0x1FE0) + ((tileMap + 1) & 0x001F) x += 8 - def getPattern(self, address): + def get_pattern(self, address): pattern = self.vram[address] & 0xFF pattern +=(self.vram[address + 1] & 0xFF) << 8 return pattern - def drawObject(self, setter): - pattern = self.getPattern(address) + def draw_object(self, setter): + pattern = self.get_pattern(address) self.mask = 0 # priority if (flags & 0x80) != 0: @@ -497,11 +502,11 @@ if (flags & 0x10) != 0: self.mask |= 0x0004 if (flags & 0x20) != 0: - self.drawObjectNormal(x, pattern, mask, setter) + self.draw_object_normal(x, pattern, mask, setter) else: - self.drawObjectFlipped(x, pattern, mask, setter) + self.draw_object_flipped(x, pattern, mask, setter) - def drawObjectNormal(self, x, pattern, mask, setter): + def draw_object_normal(self, x, pattern, mask, setter): for i in range(0, 7): color = pattern >> (6-i) if (color & 0x0202) != 0: @@ -510,7 +515,7 @@ if (color & 0x0202) != 0: setter(self, x+7, color, mask) - def drawObjectFlipped(self, x, pattern, mask, setter): + def draw_object_flipped(self, x, pattern, mask, setter): color = pattern << 1 if (color & 0x0202) != 0: setter(self, x, color | mask) @@ -519,57 +524,62 @@ if (color & 0x0202) != 0: setter(self, x + i + 1, color | mask) - def drawTile(self, x, address): - pattern = self.getPattern(address) + def draw_tile(self, x, address): + pattern = self.get_pattern(address) for i in range(0, 8): self.line[x + i] = (pattern >> (7-i)) & 0x0101 - def drawObjectTile(self, x, address, flags): - pattern = self.getPattern(address) - self.drawObject(self.setTileLine) + def draw_object_tile(self, x, address, flags): + pattern = self.get_pattern(address) + self.draw_object(self.setTileLine) - def setTileLine(self, pos, color, mask): + def set_tile_line(self, pos, color, mask): self.line[pos] |= color | mask - def drawOverlappedObjectTile(self, x, address, flags): - self.drawObject(self.setOverlappedObjectLine) + def draw_overlapped_object_tile(self, x, address, flags): + self.draw_object(self.setOverlappedObjectLine) - def setOverlappedObjectLine(self, pos, color, mask): + def set_overlapped_object_line(self, pos, color, mask): self.line[pos] = (self.line[pos] & 0x0101) | color | mask - - def drawPixels(self): - self.updatePalette() - pixels = self.driver.getPixels() - offset = self.lineY * self.driver.getWidth() + def draw_pixels(self): + self.update_palette() + pixels = self.driver.get_pixels() + offset = self.lineY * self.driver.get_width() for x in range(8, 168, 4): for i in range(0,4): pattern = self.line[x + i] pixels[offset + i] = self.palette[pattern] offset += 4 - def clearPixels(self): - self.driver.clearPixels() + def clear_pixels(self): + self.driver.clear_pixels() - def updatePalette(self): + def update_palette(self): if not self.dirty: return - # bit 4/0 = constants.BG color, bit 5/1 = constants.OBJ color, bit 2 = constants.OBJ palette, bit - # 3 = constants.OBJ priority + # bit 4/0 = constants.BG color, + # bit 5/1 = constants.OBJ color, + # bit 2 = constants.OBJ palette, + # bit 3 = constants.OBJ priority for pattern in range(0, 64): #color - if ((pattern & 0x22) == 0 or ((pattern & 0x08) != 0 and (pattern & 0x11) != 0)): + if (pattern & 0x22) == 0 or ((pattern & 0x08) != 0 and \ + (pattern & 0x11) != 0): # constants.OBJ behind constants.BG color 1-3 - color = (self.backgroundPalette >> ((((pattern >> 3) & 0x02) + (pattern & 0x01)) << 1)) & 0x03 + color = (self.backgroundPalette >> ((((pattern >> 3) & 0x02) +\ + (pattern & 0x01)) << 1)) & 0x03 # constants.OBJ above constants.BG elif ((pattern & 0x04) == 0): - color = (self.objectPalette0 >> ((((pattern >> 4) & 0x02) + ((pattern >> 1) & 0x01)) << 1)) & 0x03 + color = (self.objectPalette0 >> ((((pattern >> 4) & 0x02) + \ + ((pattern >> 1) & 0x01)) << 1)) & 0x03 else: - color = (self.objectPalette1 >> ((((pattern >> 4) & 0x02) + ((pattern >> 1) & 0x01)) << 1)) & 0x03 - self.palette[((pattern & 0x30) << 4) + (pattern & 0x0F)] = constants.COLOR_MAP[color] + color = (self.objectPalette1 >> ((((pattern >> 4) & 0x02) +\ + ((pattern >> 1) & 0x01)) << 1)) & 0x03 + index= ((pattern & 0x30) << 4) + (pattern & 0x0F) + self.palette[index] = constants.COLOR_MAP[color] self.dirty = False - # ------------------------------------------------------------------------------ class VideoDriver(object): @@ -577,20 +587,20 @@ def __init__(self): self.width = constants.GAMEBOY_SCREEN_WIDTH self.height = constants.GAMEBOY_SCREEN_HEIGHT - self.clearPixels() + self.clear_pixels() - def clearPixels(self): + def clear_pixels(self): self.pixels = [0] * self.width * self.height - def getWidth(self): + def get_width(self): return self.width - def getHeight(self): + def get_height(self): return selg.height - def getPixels(self): + def get_pixels(self): return self.pixels - def updateDisplay(self): - self.clearPixels() + def update_display(self): + self.clear_pixels() \ No newline at end of file From haypo at codespeak.net Thu May 8 14:25:24 2008 From: haypo at codespeak.net (haypo at codespeak.net) Date: Thu, 8 May 2008 14:25:24 +0200 (CEST) Subject: [pypy-svn] r54557 - pypy/dist/pypy/lib Message-ID: <20080508122524.8B6A6168506@codespeak.net> Author: haypo Date: Thu May 8 14:25:24 2008 New Revision: 54557 Added: pypy/dist/pypy/lib/pwd.py (contents, props changed) Log: Add my pwd implementation in ctypes, issue 322 Added: pypy/dist/pypy/lib/pwd.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/lib/pwd.py Thu May 8 14:25:24 2008 @@ -0,0 +1,136 @@ +# ctypes implementation: Victor Stinner, 2008-05-08 +""" +This module provides access to the Unix password database. +It is available on all Unix versions. + +Password database entries are reported as 7-tuples containing the following +items from the password database (see `'), in order: +pw_name, pw_passwd, pw_uid, pw_gid, pw_gecos, pw_dir, pw_shell. +The uid and gid items are integers, all others are strings. An +exception is raised if the entry asked for cannot be found. +""" + +from ctypes_support import standard_c_lib as libc +from ctypes import Structure, POINTER, c_int, c_char_p + +uid_t = c_int +gid_t = c_int + +class passwd(Structure): + _fields_ = ( + ("pw_name", c_char_p), + ("pw_passwd", c_char_p), + ("pw_uid", uid_t), + ("pw_gid", gid_t), + ("pw_gecos", c_char_p), + ("pw_dir", c_char_p), + ("pw_shell", c_char_p), + ) + def __iter__(self): + yield self.pw_name + yield self.pw_passwd + yield self.pw_uid + yield self.pw_gid + yield self.pw_gecos + yield self.pw_dir + yield self.pw_shell + +class struct_passwd(tuple): + """ + pwd.struct_passwd: Results from getpw*() routines. + + This object may be accessed either as a tuple of + (pw_name,pw_passwd,pw_uid,pw_gid,pw_gecos,pw_dir,pw_shell) + or via the object attributes as named in the above tuple. + """ + def __init__(self, passwd): + self.pw_name = passwd.pw_name + self.pw_passwd = passwd.pw_passwd + self.pw_uid = passwd.pw_uid + self.pw_gid = passwd.pw_gid + self.pw_gecos = passwd.pw_gecos + self.pw_dir = passwd.pw_dir + self.pw_shell = passwd.pw_shell + tuple.__init__(self, passwd) + +passwd_p = POINTER(passwd) + +_getpwuid = libc.getpwuid +_getpwuid.argtypes = (uid_t,) +_getpwuid.restype = passwd_p + +_getpwnam = libc.getpwnam +_getpwnam.argtypes = (c_char_p,) +_getpwnam.restype = passwd_p + +_setpwent = libc.setpwent +_setpwent.argtypes = None +_setpwent.restype = None + +_getpwent = libc.getpwent +_getpwent.argtypes = None +_getpwent.restype = passwd_p + +_endpwent = libc.endpwent +_endpwent.argtypes = None +_endpwent.restype = None + +def mkpwent(pw): + pw = pw.contents + return struct_passwd(pw) + +def getpwuid(uid): + """ + getpwuid(uid) -> (pw_name,pw_passwd,pw_uid, + pw_gid,pw_gecos,pw_dir,pw_shell) + Return the password database entry for the given numeric user ID. + See pwd.__doc__ for more on password database entries. + """ + pw = _getpwuid(uid) + if not pw: + raise KeyError("getpwuid(): uid not found: %s" % uid) + return mkpwent(pw) + +def getpwnam(name): + """ + getpwnam(name) -> (pw_name,pw_passwd,pw_uid, + pw_gid,pw_gecos,pw_dir,pw_shell) + Return the password database entry for the given user name. + See pwd.__doc__ for more on password database entries. + """ + pw = _getpwnam(name) + if not pw: + raise KeyError("getpwname(): name not found: %s" % name) + return mkpwent(pw) + +def getpwall(): + """ + "getpwall() -> list_of_entries + Return a list of all available password database entries, in arbitrary order. + See pwd.__doc__ for more on password database entries. + """ + users = [] + _setpwent() + while True: + pw = _getpwent() + if not pw: + break + users.append(mkpwent(pw)) + _endpwent() + return users + +__all__ = ('struct_passwd', 'getpwuid', 'getpwnam', 'getpwall') + +if __name__ == "__main__": +# Uncomment next line to test CPython implementation +# from pwd import getpwuid, getpwnam, getpwall + from os import getuid + uid = getuid() + pw = getpwuid(uid) + print "uid %s: %s" % (pw.pw_uid, pw) + name = pw.pw_name + print "name %r: %s" % (name, getpwnam(name)) + print "All:" + for pw in getpwall(): + print pw + From arigo at codespeak.net Thu May 8 14:31:00 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 8 May 2008 14:31:00 +0200 (CEST) Subject: [pypy-svn] r54558 - pypy/dist/pypy/doc Message-ID: <20080508123100.966EB16850C@codespeak.net> Author: arigo Date: Thu May 8 14:31:00 2008 New Revision: 54558 Modified: pypy/dist/pypy/doc/getting-started.txt Log: Small updates to getting-started, thanks haypo. Modified: pypy/dist/pypy/doc/getting-started.txt ============================================================================== --- pypy/dist/pypy/doc/getting-started.txt (original) +++ pypy/dist/pypy/doc/getting-started.txt Thu May 8 14:31:00 2008 @@ -50,10 +50,16 @@ CPythons core language regression tests`_. Because this invocation of PyPy still runs on top of CPython, it runs around 2000 times slower than the original CPython. - -However, since the 0.7.0 release it is possible to use PyPy to `translate +Many extension modules are not enabled by default; to use them you need +to pass ``--withmod-NAME`` arguments (for example, ``--withmod-_rawffi`` +is required to import our version of ctypes). + +This is probably not something you want to play with for too long, +though, as it is really slow. +Since the 0.7.0 release it is possible to use PyPy to `translate itself to lower level languages`_ after which it runs standalone, is not -dependant on CPython anymore and becomes faster. +dependant on CPython anymore and becomes faster (within the same speed +magnitude as CPython itself). If you are using the precompiled Windows executables, please look at the included ``README.txt`` on how to start already translated From fijal at codespeak.net Thu May 8 14:47:33 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 8 May 2008 14:47:33 +0200 (CEST) Subject: [pypy-svn] r54559 - pypy/branch/io-improvements/pypy/rpython/lltypesystem Message-ID: <20080508124733.6328A168512@codespeak.net> Author: fijal Date: Thu May 8 14:47:31 2008 New Revision: 54559 Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/lltype.py Log: Make error messages less confusing. Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/lltype.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/lltypesystem/lltype.py (original) +++ pypy/branch/io-improvements/pypy/rpython/lltypesystem/lltype.py Thu May 8 14:47:31 2008 @@ -1514,7 +1514,9 @@ self._setparentstructure(parent, baseoffset_or_fieldname) def __repr__(self): - + parent = self._wrparent() + if parent is None: + return '<_subarray at %s in already freed>' % (self._parent_index,) return '<_subarray at %r in %r>' % (self._parent_index, self._parentstructure(check=False)) From haypo at codespeak.net Thu May 8 15:12:26 2008 From: haypo at codespeak.net (haypo at codespeak.net) Date: Thu, 8 May 2008 15:12:26 +0200 (CEST) Subject: [pypy-svn] r54560 - pypy/dist/pypy/lib Message-ID: <20080508131226.233201683D0@codespeak.net> Author: haypo Date: Thu May 8 15:12:25 2008 New Revision: 54560 Modified: pypy/dist/pypy/lib/resource.py Log: Fix "from resource import *": only export existing optional constants Modified: pypy/dist/pypy/lib/resource.py ============================================================================== --- pypy/dist/pypy/lib/resource.py (original) +++ pypy/dist/pypy/lib/resource.py Thu May 8 15:12:25 2008 @@ -58,9 +58,11 @@ rlim_t = config['rlim_t'] for key in _CONSTANTS: globals()[key] = config[key] +optional_constants = [] for key in _OPTIONAL_CONSTANTS: if config[key] is not None: globals()[key] = config[key] + optional_constants.append(key) del config class ResourceError(OSError): @@ -170,8 +172,10 @@ # Irix 5.3 has _SC_PAGESIZE, but not _SC_PAGE_SIZE return sysconf("SC_PAGESIZE") -__all__ = _CONSTANTS + _OPTIONAL_CONSTANTS + ( +__all__ = _CONSTANTS + tuple(optional_constants) + ( 'ResourceError', 'timeval', 'struct_rusage', 'rlimit', 'getrusage', 'getrlimit', 'setrlimit', 'getpagesize', ) +del optional_constants + From haypo at codespeak.net Thu May 8 15:15:13 2008 From: haypo at codespeak.net (haypo at codespeak.net) Date: Thu, 8 May 2008 15:15:13 +0200 (CEST) Subject: [pypy-svn] r54561 - pypy/dist/pypy/lib Message-ID: <20080508131513.5AF49168527@codespeak.net> Author: haypo Date: Thu May 8 15:15:12 2008 New Revision: 54561 Added: pypy/dist/pypy/lib/syslog.py (contents, props changed) Log: Copy my ctypes implementation of syslog module Added: pypy/dist/pypy/lib/syslog.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/lib/syslog.py Thu May 8 15:15:12 2008 @@ -0,0 +1,129 @@ +# ctypes implementation: Victor Stinner, 2008-05-08 +""" +This module provides an interface to the Unix syslog library routines. +Refer to the Unix manual pages for a detailed description of the +syslog facility. +""" + +from ctypes_support import standard_c_lib as libc +from ctypes import c_int, c_char_p +from ctypes_configure.configure import (configure, + ExternalCompilationInfo, ConstantInteger, DefinedConstantInteger, + SimpleType) + +_CONSTANTS = ( + 'LOG_EMERG', + 'LOG_ALERT', + 'LOG_CRIT', + 'LOG_ERR', + 'LOG_WARNING', + 'LOG_NOTICE', + 'LOG_INFO', + 'LOG_DEBUG', + + 'LOG_PID', + 'LOG_CONS', + 'LOG_NDELAY', + + 'LOG_KERN', + 'LOG_USER', + 'LOG_MAIL', + 'LOG_DAEMON', + 'LOG_AUTH', + 'LOG_LPR', + 'LOG_LOCAL0', + 'LOG_LOCAL1', + 'LOG_LOCAL2', + 'LOG_LOCAL3', + 'LOG_LOCAL4', + 'LOG_LOCAL5', + 'LOG_LOCAL6', + 'LOG_LOCAL7', +) +_OPTIONAL_CONSTANTS = ( + 'LOG_NOWAIT', + 'LOG_PERROR', + + 'LOG_SYSLOG', + 'LOG_CRON', + 'LOG_UUCP', + 'LOG_NEWS', +) + +# Constant aliases if there are not defined +_ALIAS = ( + ('LOG_SYSLOG', 'LOG_DAEMON'), + ('LOG_CRON', 'LOG_DAEMON'), + ('LOG_NEWS', 'LOG_MAIL'), + ('LOG_UUCP', 'LOG_MAIL'), +) + +class SyslogConfigure: + _compilation_info_ = ExternalCompilationInfo(includes=['sys/syslog.h']) +for key in _CONSTANTS: + setattr(SyslogConfigure, key, ConstantInteger(key)) +for key in _OPTIONAL_CONSTANTS: + setattr(SyslogConfigure, key, DefinedConstantInteger(key)) + +config = configure(SyslogConfigure) +for key in _CONSTANTS: + globals()[key] = config[key] +optional_constants = [] +for key in _OPTIONAL_CONSTANTS: + if config[key] is not None: + globals()[key] = config[key] + optional_constants.append(key) +for alias, key in _ALIAS: + if alias in optional_constants: + continue + globals()[alias] = globals()[key] + optional_constants.append(alias) +del config + +# Real prototype is: +# void syslog(int priority, const char *format, ...); +# But we also need format ("%s") and one format argument (message) +_syslog = libc.syslog +_syslog.argtypes = (c_int, c_char_p, c_char_p) +_syslog.restype = None + +_openlog = libc.openlog +_openlog.argtypes = (c_char_p, c_int, c_int) +_openlog.restype = None + +_closelog = libc.closelog +_closelog.argtypes = None +_closelog.restype = None + +_setlogmask = libc.setlogmask +_setlogmask.argtypes = (c_int,) +_setlogmask.restype = c_int + +def openlog(ident, option, facility): + _openlog(ident, option, facility) + +def syslog(arg1, arg2=None): + if arg2 is not None: + priority, message = arg1, arg2 + else: + priority, message = LOG_INFO, arg1 + _syslog(priority, "%s", message) + +def closelog(): + _closelog() + +def setlogmask(mask): + return _setlogmask(mask) + +def LOG_MASK(pri): + return (1 << pri) + +def LOG_UPTO(pri): + return (1 << (pri + 1)) - 1 + +__all__ = _CONSTANTS + tuple(optional_constants) + ( + 'openlog', 'syslog', 'closelog', 'setlogmask', + 'LOG_MASK', 'LOG_UPTO') + +del optional_constants + From haypo at codespeak.net Thu May 8 15:34:28 2008 From: haypo at codespeak.net (haypo at codespeak.net) Date: Thu, 8 May 2008 15:34:28 +0200 (CEST) Subject: [pypy-svn] r54562 - pypy/dist/pypy/lib Message-ID: <20080508133428.337C5168530@codespeak.net> Author: haypo Date: Thu May 8 15:34:27 2008 New Revision: 54562 Modified: pypy/dist/pypy/lib/syslog.py Log: Remove useless import Modified: pypy/dist/pypy/lib/syslog.py ============================================================================== --- pypy/dist/pypy/lib/syslog.py (original) +++ pypy/dist/pypy/lib/syslog.py Thu May 8 15:34:27 2008 @@ -8,8 +8,7 @@ from ctypes_support import standard_c_lib as libc from ctypes import c_int, c_char_p from ctypes_configure.configure import (configure, - ExternalCompilationInfo, ConstantInteger, DefinedConstantInteger, - SimpleType) + ExternalCompilationInfo, ConstantInteger, DefinedConstantInteger) _CONSTANTS = ( 'LOG_EMERG', From haypo at codespeak.net Thu May 8 15:49:00 2008 From: haypo at codespeak.net (haypo at codespeak.net) Date: Thu, 8 May 2008 15:49:00 +0200 (CEST) Subject: [pypy-svn] r54563 - pypy/dist/pypy/lib Message-ID: <20080508134900.8AA962A00DB@codespeak.net> Author: haypo Date: Thu May 8 15:48:58 2008 New Revision: 54563 Modified: pypy/dist/pypy/lib/_locale.py Log: _locale: replace hardcoded values by ctypes_configure tool and declare __all__ Modified: pypy/dist/pypy/lib/_locale.py ============================================================================== --- pypy/dist/pypy/lib/_locale.py (original) +++ pypy/dist/pypy/lib/_locale.py Thu May 8 15:48:58 2008 @@ -1,28 +1,56 @@ -"""Support for POSIX locales.""" +# ctypes implementation of _locale module by Victor Stinner, 2008-03-27 +""" +Support for POSIX locales. +""" from ctypes import (Structure, POINTER, create_string_buffer, c_ubyte, c_int, c_char_p, c_wchar_p) from ctypes_support import standard_c_lib as libc from ctypes_support import get_errno +from ctypes_configure.configure import (configure, ExternalCompilationInfo, + ConstantInteger, DefinedConstantInteger, SimpleType) size_t = c_int -nl_item = c_int - -# Ubuntu Gusty i386 constants -LC_CTYPE = 0 -LC_NUMERIC = 1 -LC_TIME = 2 -LC_COLLATE = 3 -LC_MONETARY = 4 -LC_MESSAGES = 5 -LC_ALL = 6 -LC_PAPER = 7 -LC_NAME = 8 -LC_ADDRESS = 9 -LC_TELEPHONE = 10 -LC_MEASUREMENT = 11 -LC_IDENTIFICATION = 12 CHAR_MAX = 127 +_CONSTANTS = ( + 'LC_CTYPE', + 'LC_NUMERIC', + 'LC_TIME', + 'LC_COLLATE', + 'LC_MONETARY', + 'LC_MESSAGES', + 'LC_ALL', + 'LC_PAPER', + 'LC_NAME', + 'LC_ADDRESS', + 'LC_TELEPHONE', + 'LC_MEASUREMENT', + 'LC_IDENTIFICATION', +) + +class LocaleConfigure: + _compilation_info_ = ExternalCompilationInfo(includes=['locale.h']) +for key in _CONSTANTS: + setattr(LocaleConfigure, key, ConstantInteger(key)) + +config = configure(LocaleConfigure) +for key in _CONSTANTS: + globals()[key] = config[key] +del LocaleConfigure +del config + +try: + class LanginfoConfigure: + _compilation_info_ = ExternalCompilationInfo(includes=['langinfo.h']) + nl_item = SimpleType('nl_item') + config = configure(LanginfoConfigure) + nl_item = config['nl_item'] + del LanginfoConfigure + del config + HAS_LANGINFO = True +except: + HAS_LANGINFO = False + # Ubuntu Gusty i386 structure class lconv(Structure): _fields_ = ( @@ -105,13 +133,6 @@ _strxfrm.argtypes = (c_char_p, c_char_p, size_t) _strxfrm.restype = size_t -try: - _nl_langinfo = libc.nl_langinfo - _nl_langinfo.argtypes = (nl_item,) - _nl_langinfo.restype = c_char_p -except AttributeError: - _nl_langinfo = None - _gettext = libc.gettext _gettext.argtypes = (c_char_p,) _gettext.restype = c_char_p @@ -266,7 +287,11 @@ # TODO: Port code from CPython for Windows and Mac OS raise NotImplementedError() -if _nl_langinfo: +if HAS_LANGINFO: + _nl_langinfo = libc.nl_langinfo + _nl_langinfo.argtypes = (nl_item,) + _nl_langinfo.restype = c_char_p + def _NL_ITEM(category, index): return (category << 16) | index @@ -385,3 +410,12 @@ return codeset return None +__all__ = ( + 'Error', + 'setlocale', 'localeconv', 'strxfrm', 'strcoll', + 'gettext', 'dgettext', 'dcgettext', 'textdomain', + 'bindtextdomain', 'bind_textdomain_codeset', +) +if HAS_LANGINFO: + __all__ += ('nl_langinfo',) + From pypy-svn at codespeak.net Thu May 8 18:10:31 2008 From: pypy-svn at codespeak.net (VIAGRA INC) Date: Thu, 8 May 2008 18:10:31 +0200 (CEST) Subject: [pypy-svn] SALE 89% OFF Message-ID: <20080508050900.5855.qmail@host86-155-162-111.range86-155.btcentralplus.com> An HTML attachment was scrubbed... URL: From MAILER-DAEMON at codespeak.net Thu May 8 18:10:36 2008 From: MAILER-DAEMON at codespeak.net (Mail Delivery System) Date: Thu, 8 May 2008 18:10:36 +0200 (CEST) Subject: [pypy-svn] Undelivered Mail Returned to Sender Message-ID: <20080508161036.980F62A017F@codespeak.net> This is the Postfix program at host codespeak.net. I'm sorry to have to inform you that your message could not be delivered to one or more recipients. It's attached below. For further assistance, please send mail to If you do so, please include this problem report. You can delete your own text from the attached returned message. The Postfix program : Command died with status 1: "/www/mailman/mail/mailman post silva-dev". Command output: post script, list not found: silva-dev -------------- next part -------------- An embedded message was scrubbed... From: VIAGRA INC Subject: RE: SALE 89% OFF Date: Thu, 8 May 2008 18:10:35 +0200 (CEST) Size: 5298 URL: From fijal at codespeak.net Thu May 8 20:31:47 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 8 May 2008 20:31:47 +0200 (CEST) Subject: [pypy-svn] r54570 - in pypy/branch/io-improvements/pypy/rlib: . test Message-ID: <20080508183147.BC6172A01A4@codespeak.net> Author: fijal Date: Thu May 8 20:31:46 2008 New Revision: 54570 Modified: pypy/branch/io-improvements/pypy/rlib/rgc.py pypy/branch/io-improvements/pypy/rlib/rstring.py pypy/branch/io-improvements/pypy/rlib/test/test_rgc.py pypy/branch/io-improvements/pypy/rlib/test/test_rstring.py Log: Slightly change interface to something saner. Modified: pypy/branch/io-improvements/pypy/rlib/rgc.py ============================================================================== --- pypy/branch/io-improvements/pypy/rlib/rgc.py (original) +++ pypy/branch/io-improvements/pypy/rlib/rgc.py Thu May 8 20:31:46 2008 @@ -265,14 +265,13 @@ return hop.genop('malloc_resizable_buffer', vlist, resulttype=hop.r_result.lowleveltype) -def resize_buffer(ptr, new_size): +def resize_buffer(ptr, old_size, new_size): """ Resize raw buffer returned by resizable_buffer_of_shape to new size """ from pypy.rpython.lltypesystem import lltype T = lltype.typeOf(ptr).TO arrayfld = T._arrayfld arr = getattr(ptr, arrayfld) - old_size = len(arr) # we don't have any realloc on top of cpython new_ptr = lltype.malloc(T, new_size) new_ar = getattr(new_ptr, arrayfld) @@ -283,22 +282,24 @@ class ResizeBufferEntry(ExtRegistryEntry): _about_ = resize_buffer - def compute_result_annotation(self, s_ptr, s_new_size): + def compute_result_annotation(self, s_ptr, s_old_size, s_new_size): from pypy.annotation import model as annmodel from pypy.rpython.lltypesystem import rffi assert isinstance(s_ptr, annmodel.SomePtr) assert isinstance(s_new_size, annmodel.SomeInteger) + assert isinstance(s_old_size, annmodel.SomeInteger) return s_ptr def specialize_call(self, hop): from pypy.rpython.lltypesystem import lltype vlist = [hop.inputarg(hop.args_r[0], 0), - hop.inputarg(lltype.Signed, 1)] + hop.inputarg(lltype.Signed, 1), + hop.inputarg(lltype.Signed, 2)] hop.exception_is_here() return hop.genop('resize_buffer', vlist, resulttype=hop.r_result.lowleveltype) -def finish_building_buffer(ptr): +def finish_building_buffer(ptr, final_size): """ Finish building resizable buffer returned by resizable_buffer_of_shape """ return ptr @@ -306,14 +307,17 @@ class FinishBuildingBufferEntry(ExtRegistryEntry): _about_ = finish_building_buffer - def compute_result_annotation(self, s_arr): - from pypy.annotation.model import SomePtr, s_ImpossibleValue + def compute_result_annotation(self, s_arr, s_final_size): + from pypy.annotation.model import SomePtr, s_ImpossibleValue,\ + SomeInteger assert isinstance(s_arr, SomePtr) + assert isinstance(s_final_size, SomeInteger) return s_arr def specialize_call(self, hop): from pypy.rpython.lltypesystem import lltype - vlist = [hop.inputarg(hop.args_r[0], 0)] + vlist = [hop.inputarg(hop.args_r[0], 0), + hop.inputarg(hop.args_r[1], 1)] hop.exception_cannot_occur() return hop.genop('finish_building_buffer', vlist, resulttype=hop.r_result.lowleveltype) Modified: pypy/branch/io-improvements/pypy/rlib/rstring.py ============================================================================== --- pypy/branch/io-improvements/pypy/rlib/rstring.py (original) +++ pypy/branch/io-improvements/pypy/rlib/rstring.py Thu May 8 20:31:46 2008 @@ -2,6 +2,9 @@ """ String builder interface """ +from pypy.rpython.extregistry import ExtRegistryEntry +from pypy.rpython.annlowlevel import llhelper + INIT_SIZE = 100 # XXX tweak class StringBuilder(object): @@ -11,9 +14,20 @@ def append(self, s): self.l.append(s) - def append_char(self, c): - self.l.append(c) - def build(self): return "".join(self.l) +class StringBuilderEntry(ExtRegistryEntry): + _about_ = StringBuilder + + def compute_result_annotation(self, s_init_size=None): + from pypy.rpython.rbuilder import SomeStringBuilder + if s_init_size is not None: + assert s_init_size.is_constant() + init_size = s_init_size.const + else: + init_size = INIT_SIZE + return SomeStringBuilder(init_size) + + def specialize_call(self, hop): + return hop.r_result.rtyper_new(hop) Modified: pypy/branch/io-improvements/pypy/rlib/test/test_rgc.py ============================================================================== --- pypy/branch/io-improvements/pypy/rlib/test/test_rgc.py (original) +++ pypy/branch/io-improvements/pypy/rlib/test/test_rgc.py Thu May 8 20:31:46 2008 @@ -44,8 +44,8 @@ def f(): ptr = rgc.resizable_buffer_of_shape(STR, 1) ptr.chars[0] = 'a' - ptr = rgc.resize_buffer(ptr, 2) + ptr = rgc.resize_buffer(ptr, 1, 2) ptr.chars[1] = 'b' - return hlstr(rgc.finish_building_buffer(ptr)) + return hlstr(rgc.finish_building_buffer(ptr, 2)) assert f() == 'ab' Modified: pypy/branch/io-improvements/pypy/rlib/test/test_rstring.py ============================================================================== --- pypy/branch/io-improvements/pypy/rlib/test/test_rstring.py (original) +++ pypy/branch/io-improvements/pypy/rlib/test/test_rstring.py Thu May 8 20:31:46 2008 @@ -1,9 +1,10 @@ from pypy.rlib.rstring import StringBuilder +from def test_string_builder(): s = StringBuilder() s.append("a") s.append("abc") - s.append_char("a") + s.append("a") assert s.build() == "aabca" From fijal at codespeak.net Thu May 8 20:36:05 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 8 May 2008 20:36:05 +0200 (CEST) Subject: [pypy-svn] r54571 - in pypy/branch/io-improvements/pypy: rpython rpython/lltypesystem rpython/memory rpython/memory/gctransform rpython/memory/test translator/c/test Message-ID: <20080508183605.9DADC169E41@codespeak.net> Author: fijal Date: Thu May 8 20:36:02 2008 New Revision: 54571 Modified: pypy/branch/io-improvements/pypy/rpython/llinterp.py pypy/branch/io-improvements/pypy/rpython/lltypesystem/llheap.py pypy/branch/io-improvements/pypy/rpython/memory/gctransform/transform.py pypy/branch/io-improvements/pypy/rpython/memory/gcwrapper.py pypy/branch/io-improvements/pypy/rpython/memory/test/test_gc.py pypy/branch/io-improvements/pypy/rpython/memory/test/test_transformed_gc.py pypy/branch/io-improvements/pypy/translator/c/test/test_boehm.py Log: * Adapt to changes in rgc * Create missing methods in llheap Modified: pypy/branch/io-improvements/pypy/rpython/llinterp.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/llinterp.py (original) +++ pypy/branch/io-improvements/pypy/rpython/llinterp.py Thu May 8 20:36:02 2008 @@ -700,11 +700,11 @@ def op_malloc_resizable_buffer(self, obj, flags, size): return self.heap.malloc_resizable_buffer(obj, size) - def op_resize_buffer(self, obj, new_size): - return self.heap.resize_buffer(obj, new_size) + def op_resize_buffer(self, obj, old_size, new_size): + return self.heap.resize_buffer(obj, old_size, new_size) - def op_finish_building_buffer(self, obj): - return self.heap.finish_building_buffer(obj) + def op_finish_building_buffer(self, obj, size): + return self.heap.finish_building_buffer(obj, size) def op_free(self, obj, flavor): assert isinstance(flavor, str) Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/llheap.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/lltypesystem/llheap.py (original) +++ pypy/branch/io-improvements/pypy/rpython/lltypesystem/llheap.py Thu May 8 20:36:02 2008 @@ -19,3 +19,18 @@ return weakref_create(objgetter()) malloc_nonmovable = malloc + +def malloc_resizable_buffer(TP, size): + return malloc(TP, size) + +def resize_buffer(buf, old_size, new_size): + ll_str = malloc(typeOf(buf).TO, new_size) + for i in range(old_size): + ll_str.chars[i] = buf.chars[i] + return ll_str + +def finish_building_buffer(buf, final_size): + ll_str = malloc(typeOf(buf).TO, final_size) + for i in range(final_size): + ll_str.chars[i] = buf.chars[i] + return ll_str Modified: pypy/branch/io-improvements/pypy/rpython/memory/gctransform/transform.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/memory/gctransform/transform.py (original) +++ pypy/branch/io-improvements/pypy/rpython/memory/gctransform/transform.py Thu May 8 20:36:02 2008 @@ -598,7 +598,9 @@ def gct_finish_building_buffer(self, hop): op = hop.spaceop - return hop.genop('same_as', op.args, resultvar=op.result) + if self._can_realloc(): + return self._gct_resize_buffer_realloc(hop) + return hop.genop('same_as', [op.args[0]], resultvar=op.result) def varsize_malloc_helper(self, hop, flags, meth, extraargs): def intconst(c): return rmodel.inputconst(lltype.Signed, c) Modified: pypy/branch/io-improvements/pypy/rpython/memory/gcwrapper.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/memory/gcwrapper.py (original) +++ pypy/branch/io-improvements/pypy/rpython/memory/gcwrapper.py Thu May 8 20:36:02 2008 @@ -60,18 +60,18 @@ gctypelayout.zero_gc_pointers(result) return result - def resize_buffer(self, obj, new_size): + def resize_buffer(self, obj, old_size, new_size): T = lltype.typeOf(obj).TO buf = self.malloc_resizable_buffer(T, new_size) # copy contents arrayfld = T._arrayfld new_arr = getattr(buf, arrayfld) old_arr = getattr(obj, arrayfld) - for i in range(len(old_arr)): + for i in range(old_size): new_arr[i] = old_arr[i] return buf - def finish_building_buffer(self, obj): + def finish_building_buffer(self, obj, size): return obj def free(self, TYPE, flavor='gc'): Modified: pypy/branch/io-improvements/pypy/rpython/memory/test/test_gc.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/memory/test/test_gc.py (original) +++ pypy/branch/io-improvements/pypy/rpython/memory/test/test_gc.py Thu May 8 20:36:02 2008 @@ -437,9 +437,9 @@ def f(): ptr = rgc.resizable_buffer_of_shape(STR, 1) ptr.chars[0] = 'a' - ptr = rgc.resize_buffer(ptr, 2) + ptr = rgc.resize_buffer(ptr, 1, 2) ptr.chars[1] = 'b' - return len(hlstr(rgc.finish_building_buffer(ptr))) + return len(hlstr(rgc.finish_building_buffer(ptr, 2))) assert self.interpret(f, []) == 2 Modified: pypy/branch/io-improvements/pypy/rpython/memory/test/test_transformed_gc.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/memory/test/test_transformed_gc.py (original) +++ pypy/branch/io-improvements/pypy/rpython/memory/test/test_transformed_gc.py Thu May 8 20:36:02 2008 @@ -498,11 +498,11 @@ from pypy.rlib import rgc def f(): - ptr = rgc.resizable_buffer_of_shape(STR, 1) + ptr = rgc.resizable_buffer_of_shape(STR, 2) ptr.chars[0] = 'a' - ptr = rgc.resize_buffer(ptr, 2) + ptr = rgc.resize_buffer(ptr, 1, 2) ptr.chars[1] = 'b' - return len(hlstr(rgc.finish_building_buffer(ptr))) + return len(hlstr(rgc.finish_building_buffer(ptr, 2))) run = self.runner(f) assert run([]) == 2 Modified: pypy/branch/io-improvements/pypy/translator/c/test/test_boehm.py ============================================================================== --- pypy/branch/io-improvements/pypy/translator/c/test/test_boehm.py (original) +++ pypy/branch/io-improvements/pypy/translator/c/test/test_boehm.py Thu May 8 20:36:02 2008 @@ -383,11 +383,11 @@ from pypy.rlib import rgc def f(): - ptr = rgc.resizable_buffer_of_shape(STR, 1) + ptr = rgc.resizable_buffer_of_shape(STR, 2) ptr.chars[0] = 'a' - ptr = rgc.resize_buffer(ptr, 2) + ptr = rgc.resize_buffer(ptr, 1, 2) ptr.chars[1] = 'b' - return hlstr(rgc.finish_building_buffer(ptr)) == "ab" + return hlstr(rgc.finish_building_buffer(ptr, 2)) == "ab" run = self.getcompiled(f) assert run() == True From fijal at codespeak.net Thu May 8 20:37:42 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 8 May 2008 20:37:42 +0200 (CEST) Subject: [pypy-svn] r54572 - in pypy/branch/io-improvements/pypy/rpython: . lltypesystem ootypesystem test Message-ID: <20080508183742.B5E962A01A4@codespeak.net> Author: fijal Date: Thu May 8 20:37:41 2008 New Revision: 54572 Added: pypy/branch/io-improvements/pypy/rpython/lltypesystem/rbuilder.py (contents, props changed) pypy/branch/io-improvements/pypy/rpython/ootypesystem/rbuilder.py (contents, props changed) pypy/branch/io-improvements/pypy/rpython/rbuilder.py (contents, props changed) pypy/branch/io-improvements/pypy/rpython/test/test_rbuilder.py (contents, props changed) Modified: pypy/branch/io-improvements/pypy/rpython/typesystem.py Log: String builder implementation. Still needs more tests (like backend ones) Added: pypy/branch/io-improvements/pypy/rpython/lltypesystem/rbuilder.py ============================================================================== --- (empty file) +++ pypy/branch/io-improvements/pypy/rpython/lltypesystem/rbuilder.py Thu May 8 20:37:41 2008 @@ -0,0 +1,56 @@ + +from pypy.rpython.rbuilder import AbstractStringBuilderRepr +from pypy.rpython.lltypesystem import lltype +from pypy.rpython.lltypesystem.rstr import STR +from pypy.rpython.annlowlevel import llstr +from pypy.rlib import rgc + +STRINGBUILDER = lltype.GcStruct('stringbuilder', + ('allocated', lltype.Signed), + ('used', lltype.Signed), + ('buf', lltype.Ptr(STR))) + +class StringBuilderRepr(AbstractStringBuilderRepr): + lowleveltype = lltype.Ptr(STRINGBUILDER) + + @staticmethod + def ll_new(init_size): + ll_builder = lltype.malloc(STRINGBUILDER) + ll_builder.allocated = init_size + ll_builder.used = 0 + ll_builder.buf = rgc.resizable_buffer_of_shape(STR, init_size) + return ll_builder + + @staticmethod + def ll_append(ll_builder, str): + ll_str = llstr(str) + used = ll_builder.used + lgt = len(ll_str.chars) + allocated = ll_builder.allocated + needed = lgt + used + if needed >= allocated: + # XXX tune overallocation scheme + new_allocated = needed + 100 + ll_builder.buf = rgc.resize_buffer(ll_builder.buf, used, + new_allocated) + ll_builder.allocated = new_allocated + ll_str.copy_contents(ll_str, ll_builder.buf, 0, used, lgt) + ll_builder.used = used + lgt + + @staticmethod + def ll_append_char(ll_builder, char): + if ll_builder.used == ll_builder.allocated: + # XXX tune overallocation scheme + new_allocated = ll_builder.allocated + 100 + ll_builder.buf = rgc.resize_buffer(ll_builder.buf, ll_builder.used, + new_allocated) + ll_builder.allocated = new_allocated + ll_builder.buf.chars[ll_builder.used] = char + ll_builder.used += 1 + + @staticmethod + def ll_build(ll_builder): + final_size = ll_builder.used + return rgc.finish_building_buffer(ll_builder.buf, final_size) + +stringbuilder_repr = StringBuilderRepr() Added: pypy/branch/io-improvements/pypy/rpython/ootypesystem/rbuilder.py ============================================================================== --- (empty file) +++ pypy/branch/io-improvements/pypy/rpython/ootypesystem/rbuilder.py Thu May 8 20:37:41 2008 @@ -0,0 +1,24 @@ + +from pypy.rpython.rbuilder import AbstractStringBuilderRepr +from pypy.rpython.ootypesystem import ootype + +class StringBuilderRepr(AbstractStringBuilderRepr): + lowleveltype = ootype.StringBuilder + + @staticmethod + def ll_new(init_size): + return ootype.new(ootype.StringBuilder) + + @staticmethod + def ll_append_char(builder, char): + builder.ll_append_char(char) + + @staticmethod + def ll_append(builder, string): + builder.ll_append(string) + + @staticmethod + def ll_build(builder): + return builder.ll_build() + +stringbuilder_repr = StringBuilderRepr() Added: pypy/branch/io-improvements/pypy/rpython/rbuilder.py ============================================================================== --- (empty file) +++ pypy/branch/io-improvements/pypy/rpython/rbuilder.py Thu May 8 20:37:41 2008 @@ -0,0 +1,40 @@ + +from pypy.annotation.model import SomeObject, SomeString, s_None,\ + SomeChar, SomeInteger +from pypy.rpython.rmodel import Repr +from pypy.rpython.annlowlevel import llhelper +from pypy.rpython.lltypesystem import lltype + +class SomeStringBuilder(SomeObject): + def __init__(self, init_size): + self.init_size = init_size + + def method_append(self, s_str): + assert isinstance(s_str, (SomeString, SomeChar)) + return s_None + + def method_build(self): + return SomeString() + + def rtyper_makerepr(self, rtyper): + return rtyper.type_system.rbuilder.stringbuilder_repr + +class AbstractStringBuilderRepr(Repr): + def rtyper_new(self, hop): + repr = hop.r_result + if len(hop.args_v) == 0: + v_arg = hop.inputconst(lltype.Signed, hop.s_result.init_size) + else: + v_arg = hop.inputarg(lltype.Signed, 0) + return hop.gendirectcall(self.ll_new, v_arg) + + def rtype_method_append(self, hop): + vlist = hop.inputargs(*hop.args_r) + if isinstance(hop.args_s[1], SomeChar): + return hop.gendirectcall(self.ll_append_char, *vlist) + return hop.gendirectcall(self.ll_append, *vlist) + + def rtype_method_build(self, hop): + vlist = hop.inputargs(*hop.args_r) + return hop.gendirectcall(self.ll_build, *vlist) + Added: pypy/branch/io-improvements/pypy/rpython/test/test_rbuilder.py ============================================================================== --- (empty file) +++ pypy/branch/io-improvements/pypy/rpython/test/test_rbuilder.py Thu May 8 20:37:41 2008 @@ -0,0 +1,29 @@ + +from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin +from pypy.rlib.rstring import StringBuilder + +class BaseTestStringBuilder(BaseRtypingTest): + def test_simple(self): + def func(): + s = StringBuilder() + s.append("a") + s.append("abc") + return s.build() + res = self.ll_to_string(self.interpret(func, [])) + assert res == "aabc" + + def test_overallocation(self): + def func(): + s = StringBuilder(4) + s.append("abcd") + s.append("defg") + s.append("rty") + return s.build() + res = self.ll_to_string(self.interpret(func, [])) + assert res == "abcddefgrty" + +class TestLLtype(BaseTestStringBuilder, LLRtypeMixin): + pass + +class TestOOtype(BaseTestStringBuilder, OORtypeMixin): + pass Modified: pypy/branch/io-improvements/pypy/rpython/typesystem.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/typesystem.py (original) +++ pypy/branch/io-improvements/pypy/rpython/typesystem.py Thu May 8 20:37:41 2008 @@ -22,7 +22,7 @@ return None if name in ('rclass', 'rpbc', 'rbuiltin', 'rtuple', 'rlist', 'rslice', 'rdict', 'rrange', 'rstr', 'rgeneric', - 'll_str', 'exceptiondata'): + 'll_str', 'rbuilder', 'exceptiondata'): mod = load(name) if mod is not None: setattr(self, name, mod) From arigo at codespeak.net Thu May 8 22:07:47 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 8 May 2008 22:07:47 +0200 (CEST) Subject: [pypy-svn] r54573 - pypy/dist/pypy/translator/c/src Message-ID: <20080508200747.4C133398002@codespeak.net> Author: arigo Date: Thu May 8 22:07:45 2008 New Revision: 54573 Modified: pypy/dist/pypy/translator/c/src/int.h Log: Fix prototype. Modified: pypy/dist/pypy/translator/c/src/int.h ============================================================================== --- pypy/dist/pypy/translator/c/src/int.h (original) +++ pypy/dist/pypy/translator/c/src/int.h Thu May 8 22:07:45 2008 @@ -241,7 +241,7 @@ /* prototypes */ -op_int_mul_ovf(long a, long b, long *longprod); +int op_int_mul_ovf(long a, long b, long *longprod); /* implementations */ From arigo at codespeak.net Thu May 8 22:08:09 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 8 May 2008 22:08:09 +0200 (CEST) Subject: [pypy-svn] r54574 - pypy/dist/pypy/translator/benchmark Message-ID: <20080508200809.122D0398002@codespeak.net> Author: arigo Date: Thu May 8 22:08:08 2008 New Revision: 54574 Modified: pypy/dist/pypy/translator/benchmark/bench-custom.py Log: Print an empty line for nicer readability. Modified: pypy/dist/pypy/translator/benchmark/bench-custom.py ============================================================================== --- pypy/dist/pypy/translator/benchmark/bench-custom.py (original) +++ pypy/dist/pypy/translator/benchmark/bench-custom.py Thu May 8 22:08:08 2008 @@ -76,6 +76,7 @@ for row in benchmark_result.txt_summary(['exe'] + exe_stats, **kwds): print row + print if __name__ == '__main__': from optparse import OptionParser From arigo at codespeak.net Thu May 8 22:54:58 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 8 May 2008 22:54:58 +0200 (CEST) Subject: [pypy-svn] r54575 - in pypy/dist/pypy: interpreter interpreter/pyparser module/recparser Message-ID: <20080508205458.0F34C39B5BA@codespeak.net> Author: arigo Date: Thu May 8 22:54:56 2008 New Revision: 54575 Modified: pypy/dist/pypy/interpreter/pycompiler.py pypy/dist/pypy/interpreter/pyparser/pythonutil.py pypy/dist/pypy/module/recparser/pyparser.py Log: In the 'recparser' module: don't reload the Grammar file at runtime, but just reuse the prebuilt parser object from the object space's compiler. Avoids a "fatal rpython error: OSError" if the Grammar file is not found at the path that was hard-coded in the pypy-c. Modified: pypy/dist/pypy/interpreter/pycompiler.py ============================================================================== --- pypy/dist/pypy/interpreter/pycompiler.py (original) +++ pypy/dist/pypy/interpreter/pycompiler.py Thu May 8 22:54:56 2008 @@ -285,6 +285,17 @@ assert isinstance(c, PyCode) return c + # interface for pypy.module.recparser + def get_parser(self): + return self.parser + + def source2ast(self, source, mode='exec'): + from pypy.interpreter.pyparser.astbuilder import AstBuilder + builder = AstBuilder(self.parser, self.grammar_version, + space=self.space) + self.parser.parse_source(source, mode, builder) + return builder.rule_stack[-1] + def install_compiler_hook(space, w_callable): # if not space.get( w_callable ): Modified: pypy/dist/pypy/interpreter/pyparser/pythonutil.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/pythonutil.py (original) +++ pypy/dist/pypy/interpreter/pyparser/pythonutil.py Thu May 8 22:54:56 2008 @@ -26,7 +26,13 @@ def get_grammar_file(version): - """returns the python grammar corresponding to our CPython version""" + """NOT_RPYTHON + Returns the python grammar corresponding to our CPython version.""" + # building parsers at run-time kind of works, but the logic to load + # the grammar file from pypy/interpreter/pyparser/data/, moreover with + # a hard-coded absolute path, makes little sense in a translated PyPy. + # This is why this function is marked as NOT_RPYTHON. + if version == "native": _ver = PYTHON_VERSION elif version == "stable": Modified: pypy/dist/pypy/module/recparser/pyparser.py ============================================================================== --- pypy/dist/pypy/module/recparser/pyparser.py (original) +++ pypy/dist/pypy/module/recparser/pyparser.py Thu May 8 22:54:56 2008 @@ -8,7 +8,6 @@ from pypy.interpreter.typedef import interp_attrproperty, GetSetProperty from pypy.interpreter.pycode import PyCode from pypy.interpreter.pyparser.syntaxtree import TokenNode, SyntaxNode, AbstractSyntaxVisitor -from pypy.interpreter.pyparser.pythonparse import make_pyparser from pypy.interpreter.pyparser.error import SyntaxError from pypy.interpreter.pyparser import grammar, symbol, pytoken from pypy.interpreter.argument import Arguments @@ -150,8 +149,17 @@ totuple = interp2app(STType.descr_totuple), ) +def get_ast_compiler(space): + from pypy.interpreter.pycompiler import PythonAstCompiler + compiler = space.createcompiler() + if not isinstance(compiler, PythonAstCompiler): + raise OperationError(space.w_RuntimeError, + space.wrap("not implemented in a PyPy with " + "a non-AST compiler")) + return compiler + def parse_python_source(space, source, mode): - parser = make_pyparser(space.config.objspace.pyversion) + parser = get_ast_compiler(space).get_parser() builder = grammar.BaseGrammarBuilder(debug=False, parser=parser) builder.space = space try: @@ -205,8 +213,8 @@ def source2ast(space, source): - from pypy.interpreter.pyparser.pythonutil import source2ast - return space.wrap(source2ast(source, 'exec', space=space)) + compiler = get_ast_compiler(space) + return space.wrap(compiler.source2ast(source, 'exec')) source2ast.unwrap_spec = [ObjSpace, str] From antocuni at codespeak.net Fri May 9 00:33:52 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 9 May 2008 00:33:52 +0200 (CEST) Subject: [pypy-svn] r54577 - pypy/extradoc/talk/pycon-italy-2008 Message-ID: <20080508223352.1E1F439B5E5@codespeak.net> Author: antocuni Date: Fri May 9 00:33:51 2008 New Revision: 54577 Added: pypy/extradoc/talk/pycon-italy-2008/rainbow.png (contents, props changed) Modified: pypy/extradoc/talk/pycon-italy-2008/pypy-vm.pdf pypy/extradoc/talk/pycon-italy-2008/technical.txt Log: add an image of a rainbow Modified: pypy/extradoc/talk/pycon-italy-2008/pypy-vm.pdf ============================================================================== Files pypy/extradoc/talk/pycon-italy-2008/pypy-vm.pdf (original) and pypy/extradoc/talk/pycon-italy-2008/pypy-vm.pdf Fri May 9 00:33:51 2008 differ Added: pypy/extradoc/talk/pycon-italy-2008/rainbow.png ============================================================================== Binary file. No diff available. Modified: pypy/extradoc/talk/pycon-italy-2008/technical.txt ============================================================================== --- pypy/extradoc/talk/pycon-italy-2008/technical.txt (original) +++ pypy/extradoc/talk/pycon-italy-2008/technical.txt Fri May 9 00:33:51 2008 @@ -286,6 +286,12 @@ The Rainbow interpreter ================================== +.. raw:: latex + + {\vspace{-1cm}\hfill\scalebox{0.300000}{\includegraphics{rainbow.png}}} + + \addvspace{0.3cm} + * A special interpreter whose goal is to produce executable code * Written in RPython From arigo at codespeak.net Fri May 9 10:44:58 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 9 May 2008 10:44:58 +0200 (CEST) Subject: [pypy-svn] r54578 - pypy/branch/gc-tweak/pypy/rpython/memory/gc/test Message-ID: <20080509084458.5AA7D39B639@codespeak.net> Author: arigo Date: Fri May 9 10:44:55 2008 New Revision: 54578 Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gc/test/test_direct.py Log: More tests. Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gc/test/test_direct.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/memory/gc/test/test_direct.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/memory/gc/test/test_direct.py Fri May 9 10:44:55 2008 @@ -17,6 +17,8 @@ ('prev', lltype.Ptr(S)), ('next', lltype.Ptr(S)))) RAW = lltype.Struct('RAW', ('p', lltype.Ptr(S)), ('q', lltype.Ptr(S))) +VAR = lltype.GcArray(lltype.Ptr(S)) +VARNODE = lltype.GcStruct('VARNODE', ('a', lltype.Ptr(VAR))) class DirectRootWalker(object): @@ -82,8 +84,16 @@ self.gc.write_barrier(oldaddr, newaddr, addr_struct) setattr(p, fieldname, newvalue) - def malloc(self, TYPE): - addr = self.gc.malloc(self.get_type_id(TYPE)) + def writearray(self, p, index, newvalue): + if self.gc.needs_write_barrier: + oldaddr = llmemory.cast_ptr_to_adr(p[index]) + newaddr = llmemory.cast_ptr_to_adr(newvalue) + addr_struct = llmemory.cast_ptr_to_adr(p) + self.gc.write_barrier(oldaddr, newaddr, addr_struct) + p[index] = newvalue + + def malloc(self, TYPE, n=None): + addr = self.gc.malloc(self.get_type_id(TYPE), n) return llmemory.cast_adr_to_ptr(addr, lltype.Ptr(TYPE)) def test_simple(self): @@ -174,6 +184,60 @@ a1, a2 = alloc2(i) growloop(raw.p, a1, a2) + def test_varsized_from_stack(self): + expected = {} + def verify(): + for (index, index2), value in expected.items(): + assert self.stackroots[index][index2].x == value + x = 0 + for i in range(40): + self.stackroots.append(self.malloc(VAR, i)) + for j in range(5): + p = self.malloc(S) + p.x = x + index = x % len(self.stackroots) + if index > 0: + index2 = (x / len(self.stackroots)) % index + a = self.stackroots[index] + assert len(a) == index + self.writearray(a, index2, p) + expected[index, index2] = x + x += 1291 + verify() + self.gc.collect() + verify() + self.gc.collect() + verify() + + def test_varsized_from_prebuilt_gc(self): + expected = {} + def verify(): + for (index, index2), value in expected.items(): + assert prebuilt[index].a[index2].x == value + x = 0 + prebuilt = [lltype.malloc(VARNODE, immortal=True, zero=True) + for i in range(40)] + for node in prebuilt: + self.consider_constant(node) + for i in range(len(prebuilt)): + self.write(prebuilt[i], 'a', self.malloc(VAR, i)) + for j in range(20): + p = self.malloc(S) + p.x = x + index = x % (i+1) + if index > 0: + index2 = (x / (i+1)) % index + a = prebuilt[index].a + assert len(a) == index + self.writearray(a, index2, p) + expected[index, index2] = x + x += 1291 + verify() + self.gc.collect() + verify() + self.gc.collect() + verify() + class TestSemiSpaceGC(DirectGCTest): from pypy.rpython.memory.gc.semispace import SemiSpaceGC as GCClass @@ -183,3 +247,11 @@ class TestHybridGC(TestGenerationGC): from pypy.rpython.memory.gc.hybrid import HybridGC as GCClass + + GC_PARAMS = {'space_size': 192, + 'min_nursery_size': 48, + 'nursery_size': 48, + 'large_object': 12, + 'large_object_gcptrs': 12, + 'generation3_collect_threshold': 5, + } From cami at codespeak.net Fri May 9 11:16:21 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Fri, 9 May 2008 11:16:21 +0200 (CEST) Subject: [pypy-svn] r54579 - in pypy/branch/gameboy-emulator/pypy/lang/gameboy: . test Message-ID: <20080509091621.61AA739B66E@codespeak.net> Author: cami Date: Fri May 9 11:16:20 2008 New Revision: 54579 Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboy.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboyImplementation.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/interrupt.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/joypad.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/ram.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cpu.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_interrupt.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_joypad.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_ram.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_register.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_timer.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/timer.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/video.py Log: made isntacne variables underscored Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py Fri May 9 11:16:20 2008 @@ -4,22 +4,22 @@ from pypy.lang.gameboy import constants import os -def has_cartridge_battery(self, cartridgeType): - return (cartridgeType == constants.TYPE_MBC1_RAM_BATTERY \ - or cartridgeType == constants.TYPE_MBC2_BATTERY \ - or cartridgeType == constants.TYPE_MBC3_RTC_BATTERY \ - or cartridgeType == constants.TYPE_MBC3_RTC_RAM_BATTERY \ - or cartridgeType == constants.TYPE_MBC3_RAM_BATTERY \ - or cartridgeType == constants.TYPE_MBC5_RAM_BATTERY \ - or cartridgeType == constants.TYPE_MBC5_RUMBLE_RAM_BATTERY \ - or cartridgeType == constants.TYPE_HUC1_RAM_BATTERY) - - -def create_bank_controller(self, cartridgeType, rom, ram, clock): - if constants.CATRIDGE_TYPE_MAPPING.has_key(cartridgeType) : - return constants.CATRIDGE_TYPE_MAPPING[cartridgeType](rom, ram, clock) +def has_cartridge_battery(self, cartridge_type): + return (cartridge_type == constants.TYPE_MBC1_RAM_BATTERY \ + or cartridge_type == constants.TYPE_MBC2_BATTERY \ + or cartridge_type == constants.TYPE_MBC3_RTC_BATTERY \ + or cartridge_type == constants.TYPE_MBC3_RTC_RAM_BATTERY \ + or cartridge_type == constants.TYPE_MBC3_RAM_BATTERY \ + or cartridge_type == constants.TYPE_MBC5_RAM_BATTERY \ + or cartridge_type == constants.TYPE_MBC5_RUMBLE_RAM_BATTERY \ + or cartridge_type == constants.TYPE_HUC1_RAM_BATTERY) + + +def create_bank_controller(self, cartridge_type, rom, ram, clock): + if constants.CATRIDGE_TYPE_MAPPING.has_key(cartridge_type) : + return constants.CATRIDGE_TYPE_MAPPING[cartridge_type](rom, ram, clock) else: - raise InvalidMemoryBankTypeError("Unsupported memory bank controller (0x"+hex(cartridgeType)+")") + raise InvalidMemoryBankTypeError("Unsupported memory bank controller (0x"+hex(cartridge_type)+")") class InvalidMemoryBankTypeError(Exception): pass @@ -31,8 +31,8 @@ class CartridgeManager(object): - def __init__(self, clockDriver): - self.clock = clockDriver + def __init__(self, clock_driver): + self.clock = clock_driver self.cartridge = None def reset(self): @@ -127,8 +127,8 @@ checksum = (checksum - (self.rom[address] & 0xFF)) & 0xFF return (checksum == self.get_header_checksum()) - def create_bank_controller(self, type, rom, ram, clockDriver): - return MEMORY_BANK_MAPPING[type](rom, ram, clockDriver) + def create_bank_controller(self, type, rom, ram, clock_driver): + return MEMORY_BANK_MAPPING[type](rom, ram, clock_driver) # ------------------------------------------------------------------------------ @@ -211,26 +211,26 @@ class MBC(object): - def __init__(self, rom, ram, clockDriver): + def __init__(self, rom, ram, clock_driver): self.set_rom(rom) self.set_ram(ram) def reset(self): - self.romBank = constants.ROM_BANK_SIZE - self.ramBank = 0 + self.rom_bank = constants.ROM_BANK_SIZE + self.ram_bank = 0 self.ramEnable = False self.rom = [] self.ram = [] self.romSize = 0 self.ramSize = 0 - self.minRomBankSize = 0 - self.maxRomBankSize = 0 - self.minRamBankSize = 0 - self.maxRamBankSize = 0 + self.min_rom_bank_size = 0 + self.max_rom_bank_size = 0 + self.min_ram_bank_size = 0 + self.max_ram_bank_size = 0 def set_rom(self, buffer): banks = len(buffer) / constants.ROM_BANK_SIZE - if banks < self.minRomBankSize or banks > self.maxRomBankSize: + if banks < self.min_rom_bank_size or banks > self.max_rom_bank_size: raise Exception("Invalid constants.ROM size") self.rom = buffer self.romSize = constants.ROM_BANK_SIZE*banks - 1 @@ -238,7 +238,7 @@ def set_ram(self, buffer): banks = len(buffer) / constants.RAM_BANK_SIZE - if banks < self.minRamBankSize or banks > self.maxRamBankSize: + if banks < self.min_ram_bank_size or banks > self.max_ram_bank_size: raise Exception("Invalid constants.RAM size") self.ram = buffer self.ramSize = constants.RAM_BANK_SIZE*banks - 1 @@ -248,10 +248,10 @@ if address <= 0x3FFF: # 0000-3FFF return self.rom[address] & 0xFF elif address <= 0x7FFF:# 4000-7FFF - print address, self.romBank - return self.rom[self.romBank + (address & 0x3FFF)] & 0xFF + print address, self.rom_bank + return self.rom[self.rom_bank + (address & 0x3FFF)] & 0xFF elif address >= 0xA000 and address <= 0xBFFF and self.ramEnable: # A000-BFFF - return self.ram[self.ramBank + (address & 0x1FFF)] & 0xFF + return self.ram[self.ram_bank + (address & 0x1FFF)] & 0xFF return 0xFF def write(self, address, data): @@ -263,13 +263,13 @@ class DefaultMBC(MBC): - def __init__(self, rom, ram, clockDriver): + def __init__(self, rom, ram, clock_driver): self.reset() - self.minRomBankSize = 0 - self.maxRomBankSize = 0xFFFFFF - self.minRamBankSize = 0 - self.maxRamBankSize = 0xFFFFFF - MBC.__init__(self, rom, ram, clockDriver) + self.min_rom_bank_size = 0 + self.max_rom_bank_size = 0xFFFFFF + self.min_ram_bank_size = 0 + self.max_ram_bank_size = 0xFFFFFF + MBC.__init__(self, rom, ram, clock_driver) #------------------------------------------------------------------------------- @@ -285,13 +285,13 @@ 4000-7FFF ROM Bank 1-127 (16KB) A000-BFFF RAM Bank 0-3 (8KB) """ - def __init__(self, rom, ram, clockDriver): + def __init__(self, rom, ram, clock_driver): self.reset() - self.minRamBankSize = 0 - self.maxRamBankSize = 4 - self.minRomBankSize = 2 - self.maxRomBankSize = 128 - MBC.__init__(self, rom, ram, clockDriver) + self.min_ram_bank_size = 0 + self.max_ram_bank_size = 4 + self.min_rom_bank_size = 2 + self.max_rom_bank_size = 128 + MBC.__init__(self, rom, ram, clock_driver) def reset(self): MBC.reset(self) @@ -307,7 +307,7 @@ elif address <= 0x7FFF: # 6000-7FFF self.memoryModel = data & 0x01 elif address >= 0xA000 and address <= 0xBFFF and self.ramEnable: # A000-BFFF - self.ram[self.ramBank + (address & 0x1FFF)] = data + self.ram[self.ram_bank + (address & 0x1FFF)] = data def write_ram_enable(self, address, data): if self.ramSize > 0: @@ -317,15 +317,15 @@ if (data & 0x1F) == 0: data = 1 if self.memoryModel == 0: - self.romBank = ((self.romBank & 0x180000) + ((data & 0x1F) << 14)) & self.romSize + self.rom_bank = ((self.rom_bank & 0x180000) + ((data & 0x1F) << 14)) & self.romSize else: - self.romBank = ((data & 0x1F) << 14) & self.romSize + self.rom_bank = ((data & 0x1F) << 14) & self.romSize def write_rom_bank_2(self, address, data): if self.memoryModel == 0: - self.romBank = ((self.romBank & 0x07FFFF) + ((data & 0x03) << 19)) & self.romSize + self.rom_bank = ((self.rom_bank & 0x07FFFF) + ((data & 0x03) << 19)) & self.romSize else: - self.ramBank = ((data & 0x03) << 13) & self.ramSize + self.ram_bank = ((data & 0x03) << 13) & self.ramSize #------------------------------------------------------------------------------- @@ -344,13 +344,13 @@ RAM_BANK_SIZE = 512 - def __init__(self, rom, ram, clockDriver): + def __init__(self, rom, ram, clock_driver): self.reset() - self.minRamBankSize = constants.RAM_BANK_SIZE - self.maxRamBankSize = constants.RAM_BANK_SIZE - self.minRomBankSize = 2 - self.maxRomBankSize = 16 - MBC.__init__(self, rom, ram, clockDriver) + self.min_ram_bank_size = constants.RAM_BANK_SIZE + self.max_ram_bank_size = constants.RAM_BANK_SIZE + self.min_rom_bank_size = 2 + self.max_rom_bank_size = 16 + MBC.__init__(self, rom, ram, clock_driver) def read(self, address): @@ -376,7 +376,7 @@ return if (data & 0x0F) == 0: data = 1 - self.romBank = ((data & 0x0F) << 14) & self.romSize + self.rom_bank = ((data & 0x0F) << 14) & self.romSize def write_ram(self, address, data): if self.ramEnable: @@ -398,45 +398,45 @@ """ def __init__(self, rom, ram, clock): self.reset() - self.minRamBankSize = 0 - self.maxRamBankSize = 4 - self.minRomBankSize = 2 - self.maxRomBankSize = 128 + self.min_ram_bank_size = 0 + self.max_ram_bank_size = 4 + self.min_rom_bank_size = 2 + self.max_rom_bank_size = 128 self.clock = clock self.clockLDaysclockLControl = None - MBC.__init__(self, rom, ram, clockDriver) + MBC.__init__(self, rom, ram, clock_driver) self.reset() def reset(self): MBC.reset(self) - self.clockTime = self.clock.getTime() - self.clockLatch = self.clockRegister = 0 + self.clock_time = self.clock.get_time() + self.clockLatch = self.clock_register = 0 self.clockSeconds = self.clockMinutes = self.clockHours = self.clockDays = self.clockControl = 0 self.clockLSeconds = self.clockLMinutes = self.clockLHours = self.clockLDays = self.clockLControl = 0 def read(self, address): if (address >= 0xA000 and address <= 0xBFFF): # A000-BFFF - if (self.ramBank >= 0): - return self.ram[self.ramBank + (address & 0x1FFF)] & 0xFF + if (self.ram_bank >= 0): + return self.ram[self.ram_bank + (address & 0x1FFF)] & 0xFF else: return self.read_clock_data(address) else: return super.read(address) def read_clock_data(self, address): - if self.clockRegister == 0x08: + if self.clock_register == 0x08: return self.clockLSeconds - if self.clockRegister == 0x09: + if self.clock_register == 0x09: return self.clockLMinutes - if self.clockRegister == 0x0A: + if self.clock_register == 0x0A: return self.clockLHours - if self.clockRegister == 0x0B: + if self.clock_register == 0x0B: return self.clockLDays - if self.clockRegister == 0x0C: + if self.clock_register == 0x0C: return self.clockLControl def write(self, address, data): @@ -458,14 +458,14 @@ def write_rom_bank(self, address, data): if data == 0: data = 1 - self.romBank = ((data & 0x7F) << 14) & self.romSize + self.rom_bank = ((data & 0x7F) << 14) & self.romSize def write_ram_bank(self, address, data): if data >= 0x00 and data <= 0x03: - self.ramBank = (data << 13) & self.ramSize + self.ram_bank = (data << 13) & self.ramSize else: - self.ramBank = -1 - self.clockRegister = data + self.ram_bank = -1 + self.clock_register = data def write_clock_latch(self, address, data): if self.clockLatch == 0 and data == 1: @@ -474,19 +474,19 @@ self.clockLatch = data def write_clock_data(self, address, data): - if self.ramBank >= 0: - self.ram[self.ramBank + (address & 0x1FFF)] = data + if self.ram_bank >= 0: + self.ram[self.ram_bank + (address & 0x1FFF)] = data else: self.updateClock() - if self.clockRegister == 0x08: + if self.clock_register == 0x08: self.clockSeconds = data - if self.clockRegister == 0x09: + if self.clock_register == 0x09: self.clockMinutes = data - if self.clockRegister == 0x0A: + if self.clock_register == 0x0A: self.clockHours = data - if self.clockRegister == 0x0B: + if self.clock_register == 0x0B: self.clockDays = data - if self.clockRegister == 0x0C: + if self.clock_register == 0x0C: self.clockControl = (self.clockControl & 0x80) | data @@ -502,7 +502,7 @@ def update_clock(): now = self.clock.get_time() if (self.clockControl & 0x40) == 0: - elapsed = now - self.clockTime + elapsed = now - self.clock_time while elapsed >= 246060: elapsed -= 246060 self.clockDays+=1 @@ -525,7 +525,7 @@ while self.clockDays >= 512: self.clockDays -= 512 self.clockControl |= 0x80 - self.clockTime = now + self.clock_time = now #------------------------------------------------------------------------------- @@ -541,28 +541,28 @@ 4000-7FFF ROM Bank 1-511 (16KB) A000-BFFF RAM Bank 0-15 (8KB) """ - def __init__(self, rom, ram, clockDriver, rumble): + def __init__(self, rom, ram, clock_driver, rumble): self.reset() - self.minRamBankSize = 0 - self.maxRamBankSize = 16 - self.minRomBankSize = 2 - self.maxRomBankSize = 512 + self.min_ram_bank_size = 0 + self.max_ram_bank_size = 16 + self.min_rom_bank_size = 2 + self.max_rom_bank_size = 512 self.rumble = rumble - MBC.__init__(self, rom, ram, clockDriver) + MBC.__init__(self, rom, ram, clock_driver) def write(self, address, data): if address <= write_ram_enable: # 0000-1FFF self.writeRAMEnable(address, data) elif address <= 0x2FFF: # 2000-2FFF - self.romBank = ((self.romBank & (0x01 << 22)) + ((data & 0xFF) << 14)) & self.romSize + self.rom_bank = ((self.rom_bank & (0x01 << 22)) + ((data & 0xFF) << 14)) & self.romSize elif address <= 0x3FFF: # 3000-3FFF - self.romBank = ((self.romBank & (0xFF << 14)) + ((data & 0x01) << 22)) & self.romSize + self.rom_bank = ((self.rom_bank & (0xFF << 14)) + ((data & 0x01) << 22)) & self.romSize elif address <= 0x4FFF: # 4000-4FFF self.write_ram_bank(address, data) elif address >= 0xA000 and address <= 0xBFFF and self.ramEnable: # A000-BFFF - self.ram[self.ramBank + (address & 0x1FFF)] = data + self.ram[self.ram_bank + (address & 0x1FFF)] = data def write_ram_enable(self, address, data): if self.ramSize > 0: @@ -570,18 +570,18 @@ def write_ram_bank(self, address, data): if self.rumble: - self.ramBank = ((data & 0x07) << 13) & self.ramSize + self.ram_bank = ((data & 0x07) << 13) & self.ramSize else: - self.ramBank = ((data & 0x0F) << 13) & self.ramSize + self.ram_bank = ((data & 0x0F) << 13) & self.ramSize #------------------------------------------------------------------------------- class HuC1(MBC): - def __init__(self, ram, rom, clockDriver): + def __init__(self, ram, rom, clock_driver): self.reset() - MBC.__init__(self, rom, ram, clockDriver) + MBC.__init__(self, rom, ram, clock_driver) @@ -601,65 +601,64 @@ """ def __init__(self, rom, ram, clock): self.reset() - self.minRamBankSize = 0 - self.maxRamBankSize = 4 - self.minRomBankSize = 2 - self.maxRomBankSize = 128 + self.min_ram_bank_size = 0 + self.max_ram_bank_size = 4 + self.min_rom_bank_size = 2 + self.max_rom_bank_size = 128 self.clock = clock - self.clockRegister = 0 - self.clockShift = 0 - self.clockTime = 0 - + self.clock_register = 0 + self.clock_shift = 0 + self.clock_time = 0 self.set_rom(rom) self.set_ram(ram) - self.ramFlag = 0 - self.ramValue = 0 - MBC.__init__(self, rom, ram, clockDriver) + self.ram_flag = 0 + self.ram_value = 0 + MBC.__init__(self, rom, ram, clock_driver) def reset(self): MBC.reset(self) - self.ramFlag = 0 - self.ramValue = 0 - self.clockRegister = 0 - self.clockShift = 0 - self.clockTime = self.clock.get_time() + self.ram_flag = 0 + self.ram_value = 0 + self.clock_register = 0 + self.clock_shift = 0 + self.clock_time = self.clock.get_time() def read(self, address): if address >= 0xA000 and address <= 0xBFFF:# A000-BFFF - if (self.ramFlag == 0x0C): - return self.ramValue - elif (self.ramFlag == 0x0D): + if self.ram_flag == 0x0C: + return self.ram_value + elif self.ram_flag == 0x0D: return 0x01 - elif (self.ramFlag == 0x0A or self.ramFlag == 0x00): - if (self.ramSize > 0): - return self.ram[self.ramBank + (address & 0x1FFF)] & 0xFF + elif self.ram_flag == 0x0A or self.ram_flag == 0x00: + if self.ramSize > 0: + return self.ram[self.ram_bank + (address & 0x1FFF)] & 0xFF else: super.read(address) def write(self, address, data): if address <= 0x1FFF: # 0000-1FFF - self.ramFlag = data + self.ram_flag = data elif address <= 0x3FFF:# 2000-3FFF - self.writeROMBank(address, data) + self.write_rom_bank(address, data) elif address <= 0x5FFF: # 4000-5FFF - self.ramBank = ((data & 0x0F) << 13) & self.ramSize + self.ram_bank = ((data & 0x0F) << 13) & self.ramSize elif address >= 0xA000 and address <= 0xBFFF: # A000-BFFF - self.writeRAMFlag(address, data) + self.write_ram_flag(address, data) def write_rom_bank(self, address, data): if (data & 0x7F) == 0: data = 1 - self.romBank = ((data & 0x7F) << 14) & self.romSize + self.rom_bank = ((data & 0x7F) << 14) & self.romSize def write_ram_flag(self, address, data): - if self.ramFlag == 0x0B: - self.writeWithRamFlag0x0B(address, data) - elif (self.ramFlag >= 0x0C and self.ramFlag <= 0x0E): + if self.ram_flag == 0x0B: + self.write_with_ram_flag_0x0B(address, data) + elif self.ram_flag >= 0x0C and self.ram_flag <= 0x0E: pass - elif self.ramFlag == 0x0A and self.ramSize > 0: - self.ram[self.ramBank + (address & 0x1FFF)] = data + elif self.ram_flag == 0x0A and self.ramSize > 0: + self.ram[self.ram_bank + (address & 0x1FFF)] = data def write_with_ram_flag_0x0B(self, address, data): if (data & 0xF0) == 0x10: @@ -671,51 +670,51 @@ elif (data & 0xF0) == 0x50: pass elif (data & 0xF0) == 0x60: - self.ramValue = 0x01 + self.ram_value = 0x01 def write_ram_value_clock_shift(self, address, data): - if self.clockShift > 24: + if self.clock_shift > 24: return - self.ramValue = (self.clockRegister >> self.clockShift) & 0x0F - self.clockShift += 4 + self.ram_value = (self.clock_register >> self.clock_shift) & 0x0F + self.clock_shift += 4 def write_clock_register_clock_shift(self, address, data): - if self.clockShift > 24: + if self.clock_shift > 24: return - self.clockRegister &= ~(0x0F << self.clockShift) - self.clockRegister |= ((data & 0x0F) << self.clockShift) - self.clockShift += 4 + self.clock_register &= ~(0x0F << self.clock_shift) + self.clock_register |= ((data & 0x0F) << self.clock_shift) + self.clock_shift += 4 def write_clock_shift(self, address, data): switch = data & 0x0F - self.updateClock() + self.update_clock() if switch == 0: - self.clockShift = 0 + self.clock_shift = 0 elif switch == 3: - self.clockShift = 0 + self.clock_shift = 0 elif switch == 7: - self.clockShift = 0 + self.clock_shift = 0 def update_clock(self): - now = self.clock.getTime() - elapsed = now - self.clockTime + now = self.clock.get_time() + elapsed = now - self.clock_time # years (4 bits) while elapsed >= 365246060: - self.clockRegister += 1 << 24 + self.clock_register += 1 << 24 elapsed -= 365246060 # days (12 bits) while elapsed >= 246060: - self.clockRegister += 1 << 12 + self.clock_register += 1 << 12 elapsed -= 246060 # minutes (12 bits) while elapsed >= 60: - self.clockRegister += 1 + self.clock_register += 1 elapsed -= 60 - if (self.clockRegister & 0x0000FFF) >= 2460: - self.clockRegister += (1 << 12) - 2460 - if (self.clockRegister & 0x0FFF000) >= (365 << 12): - self.clockRegister += (1 << 24) - (365 << 12) - self.clockTime = now - elapsed + if (self.clock_register & 0x0000FFF) >= 2460: + self.clock_register += (1 << 12) - 2460 + if (self.clock_register & 0x0FFF000) >= (365 << 12): + self.clock_register += (1 << 24) - (365 << 12) + self.clock_time = now - elapsed # MEMORY BANK MAPPING ---------------------------------------------------------- Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py Fri May 9 11:16:20 2008 @@ -4,33 +4,33 @@ class Register(object): def __init__(self, cpu, value=0): - self.resetValue = self.value = value + self.reset_value = self.value = value self.cpu = cpu if value != 0: self.set(value) def reset(self): - self.value = self.resetValue + self.value = self.reset_value - def set(self, value, useCycles=True): + def set(self, value, use_cycles=True): self.value = value & 0xFF - if useCycles: + if use_cycles: self.cpu.cycles -= 1 - def get(self, useCycles=True): + def get(self, use_cycles=True): return self.value - def add(self, value, useCycles=True): - self.set(self.get(useCycles)+value, useCycles) + def add(self, value, use_cycles=True): + self.set(self.get(use_cycles)+value, use_cycles) - def sub(self, value, useCycles=True): - self.set(self.get(useCycles)-value, useCycles) + def sub(self, value, use_cycles=True): + self.set(self.get(use_cycles)-value, use_cycles) #------------------------------------------------------------------------------ class DoubleRegister(object): - def __init__(self, cpu, hi=None, lo=None, resetValue=0): + def __init__(self, cpu, hi=None, lo=None, reset_value=0): self.cpu = cpu if hi == None : self.hi = Register(self.cpu) @@ -40,49 +40,49 @@ self.lo = Register(self.cpu) else: self.lo = lo - self.resetValue = resetValue + self.reset_value = reset_value - def set(self, hi=0, lo=None, useCycles=True): + def set(self, hi=0, lo=None, use_cycles=True): if lo is None: - self.set_hi(hi >> 8, useCycles) - self.set_lo(hi & 0xFF, useCycles) - if useCycles: + self.set_hi(hi >> 8, use_cycles) + self.set_lo(hi & 0xFF, use_cycles) + if use_cycles: self.cpu.cycles += 1 else: - self.set_hi(hi, useCycles) - self.set_lo(lo, useCycles) + self.set_hi(hi, use_cycles) + self.set_lo(lo, use_cycles) def reset(self): - self.set(self.resetValue, useCycles=False) + self.set(self.reset_value, use_cycles=False) - def set_hi(self, hi=0, useCycles=True): - self.hi.set(hi, useCycles) + def set_hi(self, hi=0, use_cycles=True): + self.hi.set(hi, use_cycles) - def set_lo(self, lo=0, useCycles=True): - self.lo.set(lo, useCycles) + def set_lo(self, lo=0, use_cycles=True): + self.lo.set(lo, use_cycles) - def get(self, useCycles=True): - return (self.hi.get(useCycles)<<8) + self.lo.get(useCycles) + def get(self, use_cycles=True): + return (self.hi.get(use_cycles)<<8) + self.lo.get(use_cycles) - def get_hi(self, useCycles=True): - return self.hi.get(useCycles) + def get_hi(self, use_cycles=True): + return self.hi.get(use_cycles) - def get_lo(self, useCycles=True): - return self.lo.get(useCycles) + def get_lo(self, use_cycles=True): + return self.lo.get(use_cycles) - def inc(self, useCycles=True): - self.set(self.get(useCycles) +1, useCycles=useCycles) - if useCycles: + def inc(self, use_cycles=True): + self.set(self.get(use_cycles) +1, use_cycles=use_cycles) + if use_cycles: self.cpu.cycles -= 1 - def dec(self, useCycles=True): - self.set(self.get(useCycles) - 1, useCycles=useCycles) - if useCycles: + def dec(self, use_cycles=True): + self.set(self.get(use_cycles) - 1, use_cycles=use_cycles) + if use_cycles: self.cpu.cycles -= 1 - def add(self, n=2, useCycles=True): - self.set(self.get(useCycles) + n, useCycles=useCycles) - if useCycles: + def add(self, n=2, use_cycles=True): + self.set(self.get(use_cycles) + n, use_cycles=use_cycles) + if use_cycles: self.cpu.cycles -= 2 # ------------------------------------------------------------------------------ @@ -93,15 +93,15 @@ self.cpu = cpu self.hl = hl - def set(self, value, useCycles=True): - self.cpu.write(self.hl.get(useCycles=useCycles), value) # 2 + 0 - if not useCycles: + def set(self, value, use_cycles=True): + self.cpu.write(self.hl.get(use_cycles=use_cycles), value) # 2 + 0 + if not use_cycles: self.cpu.cycles += 2 - def get(self, useCycles=True): - if not useCycles: + def get(self, use_cycles=True): + if not use_cycles: self.cpu.cycles += 1 - return self.cpu.read(self.hl.get(useCycles=useCycles)) # 1 + return self.cpu.read(self.hl.get(use_cycles=use_cycles)) # 1 # ------------------------------------------------------------------------------ @@ -111,59 +111,59 @@ self.cpu = cpu self.reset() - def reset(self, keepZ=False, keepN=False, keepH=False, keepC=False,\ - keepP=False, keepS=False): - if not keepZ: - self.zFlag = False - if not keepN: - self.nFlag = False - if not keepH: - self.hFlag = False - if not keepC: - self.cFlag = False - if not keepP: - self.pFlag = False - if not keepS: - self.sFlag = False + def reset(self, keep_z=False, keep_n=False, keep_h=False, keep_c=False,\ + keep_p=False, keep_s=False): + if not keep_z: + self.z_flag = False + if not keep_n: + self.n_flag = False + if not keep_h: + self.h_flag = False + if not keep_c: + self.c_flag = False + if not keep_p: + self.p_flag = False + if not keep_s: + self.s_flag = False self.lower = 0x00 - def get(self, useCycles=True): + def get(self, use_cycles=True): value = 0 - value += (int(self.cFlag) << 4) - value += (int(self.hFlag) << 5) - value += (int(self.nFlag) << 6) - value += (int(self.zFlag) << 7) + value += (int(self.c_flag) << 4) + value += (int(self.h_flag) << 5) + value += (int(self.n_flag) << 6) + value += (int(self.z_flag) << 7) return value + self.lower - def set(self, value, useCycles=True): - self.cFlag = bool(value & (1 << 4)) - self.hFlag = bool(value & (1 << 5)) - self.nFlag = bool(value & (1 << 6)) - self.zFlag = bool(value & (1 << 7)) + def set(self, value, use_cycles=True): + self.c_flag = bool(value & (1 << 4)) + self.h_flag = bool(value & (1 << 5)) + self.n_flag = bool(value & (1 << 6)) + self.z_flag = bool(value & (1 << 7)) self.lower = value & 0x0F - if useCycles: + if use_cycles: self.cpu.cycles -= 1 def z_flag_compare(self, a, reset=False): - if (reset): + if reset: self.reset() if isinstance(a, (Register)): a = a.get() - self.zFlag = ((a & 0xFF) == 0) + self.z_flag = ((a & 0xFF) == 0) def c_flag_add(self, s, compare_and=0x01, reset=False): - if (reset): + if reset: self.reset() if (s & compare_and) != 0: - self.cFlag = True + self.c_flag = True def h_flag_compare(self, a, b): if (a & 0x0F) < (b & 0x0F): - self.hFlag = True + self.h_flag = True def c_flag_compare(self, a, b): if a < b: - self.cFlag = True + self.c_flag = True # # ------------------------------------------------------------------------------ @@ -197,8 +197,8 @@ self.hl = DoubleRegister(self, self.h, self.l, constants.RESET_HL) self.hli = ImmediatePseudoRegister(self, self.hl) - self.pc = DoubleRegister(self, resetValue=constants.RESET_PC) - self.sp = DoubleRegister(self, resetValue=constants.RESET_SP) + self.pc = DoubleRegister(self, reset_value=constants.RESET_PC) + self.sp = DoubleRegister(self, reset_value=constants.RESET_SP) self.a = Register(self, constants.RESET_A) self.f = FlagRegister(self) @@ -208,7 +208,7 @@ def reset(self): self.reset_registers() self.f.reset() - self.f.zFlag = True + self.f.z_flag = True self.ime = False self.halted = False self.cycles = 0 @@ -274,25 +274,25 @@ def is_z(self): """ zero flag""" - return self.f.zFlag + return self.f.z_flag def is_c(self): """ carry flag, true if the result did not fit in the register""" - return self.f.cFlag + return self.f.c_flag def is_h(self): """ half carry, carry from bit 3 to 4""" - return self.f.hFlag + return self.f.h_flag def is_n(self): """ subtract flag, true if the last operation was a subtraction""" - return self.f.nFlag + return self.f.n_flag def isS(self): - return self.f.sFlag + return self.f.s_flag def is_p(self): - return self.f.pFlag + return self.f.p_flag def is_not_z(self): return not self.is_z() @@ -327,10 +327,10 @@ self.lower_pending_interrupt() def lower_pending_interrupt(self): - for flag in self.interrupt.interruptFlags: + for flag in self.interrupt.interrupt_flags: if flag.is_pending(): self.ime = False - self.call(flag.callCode, useCycles=False) + self.call(flag.call_code, use_cycles=False) flag.set_pending(False) return @@ -354,14 +354,14 @@ self.memory.write(address, data) self.cycles -= 2 - def fetch(self, useCycles=True): + def fetch(self, use_cycles=True): # Fetching 1 cycle self.cycles += 1 - if self.pc.get(useCycles) <= 0x3FFF: - data = self.rom[self.pc.get(useCycles)] + if self.pc.get(use_cycles) <= 0x3FFF: + data = self.rom[self.pc.get(use_cycles)] else: - data = self.memory.read(self.pc.get(useCycles)) - self.pc.inc(useCycles) # 2 cycles + data = self.memory.read(self.pc.get(use_cycles)) + self.pc.inc(use_cycles) # 2 cycles return data def fetch_double_address(self): @@ -372,15 +372,15 @@ def fetch_double_register(self, register): self.pop_double_register(CPU.fetch, register) - def push(self, data, useCycles=True): + def push(self, data, use_cycles=True): # Stack, 2 cycles - self.sp.dec(useCycles) # 2 cycles - self.memory.write(self.sp.get(useCycles), data) + self.sp.dec(use_cycles) # 2 cycles + self.memory.write(self.sp.get(use_cycles), data) - def push_double_register(self, register, useCycles=True): + def push_double_register(self, register, use_cycles=True): # PUSH rr 4 cycles - self.push(register.get_hi(), useCycles) # 2 cycles - self.push(register.get_lo(), useCycles) # 2 cycles + self.push(register.get_hi(), use_cycles) # 2 cycles + self.push(register.get_lo(), use_cycles) # 2 cycles def pop(self): # 1 cycle @@ -399,12 +399,12 @@ register.set(a, b) # 2 cycles self.cycles += 1 - def call(self, address, useCycles=True): + def call(self, address, use_cycles=True): # 4 cycles - self.push(self.pc.get_hi(useCycles), useCycles) # 2 cycles - self.push(self.pc.get_lo(useCycles), useCycles) # 2 cycles - self.pc.set(address, useCycles=useCycles) # 1 cycle - if useCycles: + self.push(self.pc.get_hi(use_cycles), use_cycles) # 2 cycles + self.push(self.pc.get_lo(use_cycles), use_cycles) # 2 cycles + self.pc.set(address, use_cycles=use_cycles) # 1 cycle + if use_cycles: self.cycles += 1 def ld(self, getter, setter): @@ -433,7 +433,7 @@ # 2 cycles a=1 added = (self.hl.get() + register.get()) & 0xFFFF # 1 cycle - self.f.reset(keepZ=True) + self.f.reset(keep_z=True) self.f.h_flag_compare((added >> 8), self.hl.get()) self.f.c_flag_compare(added, self.hl.get()) self.hl.set(added) @@ -443,7 +443,7 @@ # 1 cycle data = getter() s = self.a.get() + data - if self.f.cFlag: + if self.f.c_flag: s +=1 self.carry_flag_finish(s,data) @@ -451,42 +451,42 @@ # 1 cycle data = getter() s = self.a.get() - data - if self.f.cFlag: + if self.f.c_flag: s -= 1 self.carry_flag_finish(s, data) - self.f.nFlag = True + self.f.n_flag = True def carry_flag_finish(self, s, data): self.f.reset() # set the hflag if the 0x10 bit was affected if ((s ^ self.a.get() ^ data) & 0x10) != 0: - self.f.hFlag = True + self.f.h_flag = True if s >= 0x100: - self.f.cFlag= True + self.f.c_flag= True self.f.z_flag_compare(s) self.a.set(s) # 1 cycle def subtract_a(self, getter, setter=None): # 1 cycle self.compare_a(getter, setter) # 1 cycle - self.a.sub(getter(useCycles=False), False) + self.a.sub(getter(use_cycles=False), False) def fetch_subtract_a(self): data = self.fetch() - self.subtract_a(lambda useCycles=False: data) + self.subtract_a(lambda use_cycles=False: data) def compare_a(self, getter, setter=None): # 1 cycle s = (self.a.get() - getter()) & 0xFF self.f.reset() - self.f.nFlag = True + self.f.n_flag = True self.f.z_flag_compare(s) self.hc_flag_finish(s) self.cycles -= 1 def hc_flag_finish(self, data): if data > self.a.get(): - self.f.cFlag = True + self.f.c_flag = True self.f.h_flag_compare(self.a.get(), data) def AND(self, getter, setter=None): @@ -513,19 +513,19 @@ def inc(self, getter, setter): # 1 cycle data = (getter() + 1) & 0xFF - self.decIncFlagFinish(data, setter, 0x00) + self.decInc_flagFinish(data, setter, 0x00) def dec(self, getter, setter): # 1 cycle data = (getter() - 1) & 0xFF - self.decIncFlagFinish(data, setter, 0x0F) - self.f.nFlag = True + self.decInc_flagFinish(data, setter, 0x0F) + self.f.n_flag = True - def decIncFlagFinish(self, data, setter, compare): - self.f.reset(keepC=True) + def decInc_flagFinish(self, data, setter, compare): + self.f.reset(keep_c=True) self.f.z_flag_compare(data) if (data & 0x0F) == compare: - self.f.hFlag = True + self.f.h_flag = True setter(data) # 1 cycle def rotate_left_circular(self, getter, setter): @@ -542,7 +542,7 @@ def rotate_left(self, getter, setter): # 1 cycle s = (getter() << 1) & 0xFF - if self.f.cFlag: + if self.f.c_flag: s += 0x01 self.flags_and_setter_finish(s, setter, 0x80) # 1 cycle @@ -563,7 +563,7 @@ def rotate_right(self, getter, setter): # 1 cycle s = (getter() >> 1) - if self.f.cFlag: + if self.f.c_flag: s += 0x08 self.flags_and_setter_finish(s, setter) # 1 cycle @@ -603,11 +603,11 @@ def test_bit(self, getter, setter, n): # 2 cycles - self.f.reset(keepC=True) - self.f.hFlag = True - self.f.zFlag = False + self.f.reset(keep_c=True) + self.f.h_flag = True + self.f.z_flag = False if (getter() & (1 << n)) == 0: - self.f.zFlag = True + self.f.z_flag = True self.cycles -= 1 def set_bit(self, getter, setter, n): @@ -698,8 +698,8 @@ def complement_a(self): # CPA self.a.set(self.a.get() ^ 0xFF) - self.f.nFlag = True - self.f.hFlag = True + self.f.n_flag = True + self.f.h_flag = True def decimal_adjust_accumulator(self): # DAA 1 cycle @@ -718,9 +718,9 @@ self.a.set((self.a.get() + delta) & 0xFF) # 1 cycle else: self.a.set((self.a.get() - delta) & 0xFF) # 1 cycle - self.f.reset(keepN=True) + self.f.reset(keep_n=True) if delta >= 0x60: - self.f.cFlag = True + self.f.c_flag = True self.f.z_flag_compare(self.a.get()) def inc_double_register(self, register): @@ -748,24 +748,24 @@ self.f.reset() if (offset >= 0): if s < self.sp.get(): - self.f.cFlag = True + self.f.c_flag = True if (s & 0x0F00) < (self.sp.get() & 0x0F00): - self.f.hFlag = True + self.f.h_flag = True else: if s > self.sp.get(): - self.f.cFlag = True + self.f.c_flag = True if (s & 0x0F00) > (self.sp.get() & 0x0F00): - self.f.hFlag = True + self.f.h_flag = True return s def complement_carry_flag(self): # CCF/SCF - self.f.reset(keepZ=True, keepC=True) - self.f.cFlag = not self.f.cFlag + self.f.reset(keep_z=True, keep_c=True) + self.f.c_flag = not self.f.c_flag def set_carry_flag(self): - self.f.reset(keepZ=True) - self.f.cFlag = True + self.f.reset(keep_z=True) + self.f.c_flag = True def nop(self): # NOP 1 cycle @@ -824,7 +824,7 @@ def return_form_interrupt(self): # RETI 4 cycles self.ret() # 4 cycles - self.enable_interrups() # 1 cycle + others + self.enable_interrupts() # 1 cycle + others self.cycles += 1 def restart(self, nn): @@ -836,7 +836,7 @@ self.ime = False self.cycles -= 1 - def enable_interrups(self): + def enable_interrupts(self): # 1 cycle self.ime = True self.execute(self.fetch()) # 1 @@ -846,7 +846,7 @@ # HALT/STOP self.halted = True # emulate bug when interrupts are pending - if (not self.ime and self.interrupt.is_pending()): + if not self.ime and self.interrupt.is_pending(): self.execute(self.memory.read(self.pc.get())) self.handle_pending_interrupt() @@ -963,7 +963,7 @@ (0x3F, CPU.complement_carry_flag), (0x76, CPU.halt), (0xF3, CPU.disable_interrups), - (0xFB, CPU.enable_interrups), + (0xFB, CPU.enable_interrupts), (0xE2, CPU.write_a_at_expaded_c_address), (0xEA, CPU.store_a_at_fetched_address), (0xF2, CPU.store_expanded_c_in_a), Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboy.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboy.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboy.py Fri May 9 11:16:20 2008 @@ -25,27 +25,27 @@ def create_drivers(self): self.clock = Clock() - self.joypadDriver = JoypadDriver() - self.videoDriver = VideoDriver() - self.soundDriver = SoundDriver() + self.joypad_driver = JoypadDriver() + self.video_driver = VideoDriver() + self.sound_driver = SoundDriver() def create_gamboy_elements(self): self.ram = RAM() - self.cartridgeManager = CartridgeManager(self.clock) + self.cartridge_manager = CartridgeManager(self.clock) self.interrupt = Interrupt() self.cpu = CPU(self.interrupt, self) self.serial = Serial(self.interrupt) self.timer = Timer(self.interrupt) - self.joypad = Joypad(self.joypadDriver, self.interrupt) - self.video = Video(self.videoDriver, self.interrupt, self) - self.sound = Sound(self.soundDriver) + self.joypad = Joypad(self.joypad_driver, self.interrupt) + self.video = Video(self.video_driver, self.interrupt, self) + self.sound = Sound(self.sound_driver) def get_cartridge_manager(self): - return self.cartridgeManager + return self.cartridge_manager def load_cartridge(self, cartridge): - self.cartridgeManager.load(cartridge) - self.cpu.set_rom(self.cartridgeManager.get_rom()) + self.cartridge_manager.load(cartridge) + self.cpu.set_rom(self.cartridge_manager.get_rom()) def load_cartridge_file(self, path): self.load_cartridge(Cartridge(path)) @@ -75,7 +75,7 @@ self.joypad.reset() self.video.reset() self.sound.reset() - self.cpu.set_rom(self.cartridgeManager.get_rom()) + self.cpu.set_rom(self.cartridge_manager.get_rom()) self.drawLogo() def get_cycles(self): @@ -108,11 +108,11 @@ def get_receiver(self, address): if 0x0000 <= address <= 0x7FFF: - return self.cartridgeManager.get_memory_bank() + return self.cartridge_manager.get_memory_bank() elif 0x8000 <= address <= 0x9FFF: return self.video elif 0xA000 <= address <= 0xBFFF: - return self.cartridgeManager.get_memory_bank() + return self.cartridge_manager.get_memory_bank() elif 0xC000 <= address <= 0xFDFF: return self.ram elif 0xFE00 <= address <= 0xFEFF: Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboyImplementation.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboyImplementation.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboyImplementation.py Fri May 9 11:16:20 2008 @@ -25,9 +25,9 @@ def create_drivers(self): self.clock = Clock() - self.joypadDriver = JoypadDriverImplementation(self.win) - self.videoDriver = VideoDriverImplementation(self.win) - self.soundDriver = SoundDriverImplementation(self.win) + self.joypad_driver = JoypadDriverImplementation(self.win) + self.video_driver = VideoDriverImplementation(self.win) + self.sound_driver = SoundDriverImplementation(self.win) # JOYPAD DRIVER ---------------------------------------------------------------- @@ -110,7 +110,7 @@ def create_image_buffer(self): self.buffers = image.get_buffer_manager() - self.imageBuffer = self.buffers.get_color_buffer() + self.image_buffer = self.buffers.get_color_buffer() def on_resize(self, width, height): pass @@ -119,7 +119,7 @@ self.win.setSize(self.width, self.height) def update_display(self): - self.imageBuffer.blit(0, 0) + self.image_buffer.blit(0, 0) self.win.flip() Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/interrupt.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/interrupt.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/interrupt.py Fri May 9 11:16:20 2008 @@ -3,20 +3,20 @@ class InterruptFlag(object): - def __init__(self, _reset, mask, callCode): + def __init__(self, _reset, mask, call_code): self._reset = _reset self.mask = mask - self.callCode = callCode + self.call_code = call_code self.reset() def reset(self): - self.isPending = self._reset + self._is_pending = self._reset def is_pending(self): - return self.isPending + return self._is_pending - def set_pending(self, isPending=True): - self.isPending = isPending + def set_pending(self, _is_pending=True): + self._is_pending = _is_pending class Interrupt(object): @@ -28,49 +28,49 @@ def __init__(self): self.create_interrupt_flags() - self.createvflag_list() + self.create_flag_list() self.create_flag_mask_mapping() self.reset() def create_interrupt_flags(self): - self.vBlank = InterruptFlag(True, constants.VBLANK, 0x40) + self.v_blank = InterruptFlag(True, constants.VBLANK, 0x40) self.lcd = InterruptFlag(False, constants.LCD, 0x48) self.timer = InterruptFlag(False, constants.TIMER, 0x50) self.serial = InterruptFlag(False, constants.SERIAL, 0x58) self.joypad = InterruptFlag(False, constants.JOYPAD, 0x60) - def createvflag_list(self): - self.interruptFlags = [ - self.vBlank, self.lcd, + def create_flag_list(self): + self.interrupt_flags = [ + self.v_blank, self.lcd, self.timer, self.serial, self.joypad ] def create_flag_mask_mapping(self): - self.maskMapping = {} - for flag in self.interruptFlags: - self.maskMapping[flag.mask] = flag + self.mask_mapping = {} + for flag in self.interrupt_flags: + self.mask_mapping[flag.mask] = flag def reset(self): self.enable = False - for flag in self.interruptFlags: + for flag in self.interrupt_flags: flag.reset() def is_pending(self, mask=None): if not self.enable: return False if mask==None: - return self.vBlank.is_pending() - elif self.vBlank.is_pending(): - return self.maskMapping[mask].is_pending() + return self.v_blank.is_pending() + elif self.v_blank.is_pending(): + return self.mask_mapping[mask].is_pending() else: return False def raise_interrupt(self, mask): - self.maskMapping[mask].set_pending(True) + self.mask_mapping[mask].set_pending(True) def lower(self, mask): - self.maskMapping[mask].set_pending(False) + self.mask_mapping[mask].set_pending(False) def write(self, address, data): if address == constants.IE: @@ -93,13 +93,13 @@ def get_interrupt_flag(self): flag = 0x00 - for interruptFlag in self.interruptFlags: - if interruptFlag.is_pending(): - flag |= interruptFlag.mask + for interrupt_flag in self.interrupt_flags: + if interrupt_flag.is_pending(): + flag |= interrupt_flag.mask return 0xE0 | flag def set_fnterrupt_flag(self, data): - for flag in self.interruptFlags: + for flag in self.interrupt_flags: if (data & flag.mask) != 0: flag.set_pending(True) else: Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/joypad.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/joypad.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/joypad.py Fri May 9 11:16:20 2008 @@ -8,14 +8,14 @@ Joypad Input """ - def __init__(self, joypadDriver, interrupt): - self.driver = joypadDriver + def __init__(self, joypad_driver, interrupt): + self.driver = joypad_driver self.interrupt = interrupt self.reset() def reset(self): self.joyp = 0xF - self.buttonCode = 0xF + self.button_code = 0xF self.cycles = constants.JOYPAD_CLOCK def get_cycles(self): @@ -35,18 +35,18 @@ def read(self, address): if address == constants.JOYP: - return (self.joyp << 4) + self.buttonCode + return (self.joyp << 4) + self.button_code return 0xFF def update(self): - oldButtons = self.buttonCode + oldButtons = self.button_code if self.joyp == 0x1: - self.buttonCode = self.driver.get_button_code() + self.button_code = self.driver.get_button_code() elif self.joyp == 0x2: - self.buttonCode = self.driver.get_direction_code() + self.button_code = self.driver.get_direction_code() else: - self.buttonCode = 0xF - if oldButtons != self.buttonCode: + self.button_code = 0xF + if oldButtons != self.button_code: self.interrupt.raise_interrupt(constants.JOYPAD) @@ -75,10 +75,10 @@ self.create_button_groups() def add_opposite_buttons(self): - self.up.oppositeButton = self.down - self.down.oppositeButton = self.up - self.left.oppositeButton = self.right - self.right.oppositeButton = self.left + self.up.opposite_button = self.down + self.down.opposite_button = self.up + self.left.opposite_button = self.right + self.right.opposite_button = self.left def create_button_groups(self): self.directions = [self.up, self.right, self.down, self.left] @@ -165,14 +165,14 @@ class Button(object): - def __init__(self, codeValue, oppositeButton=None): - self.codeValue = codeValue - self.oppositeButton = oppositeButton + def __init__(self, code_value, opposite_button=None): + self.code_value = code_value + self.opposite_button = opposite_button self.pressed = False def get_code(self): if self.pressed: - return self.codeValue + return self.code_value else: return 0 @@ -186,8 +186,8 @@ self.pressed = False def press(self): - if self.oppositeButton is not None: - self.oppositeButton.release() + if self.opposite_button is not None: + self.opposite_button.release() self.pressed = True def is_pressed(self): Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/ram.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/ram.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/ram.py Fri May 9 11:16:20 2008 @@ -13,25 +13,25 @@ def reset(self): # Work RAM - self.wram = [0x00]*8192 + self.w_ram = [0x00]*8192 # High RAM - self.hram = [0x00]*128 + self.h_ram = [0x00]*128 def write(self, address, data): if (address >= 0xC000 and address <= 0xFDFF): # C000-DFFF Work RAM (8KB) # E000-FDFF Echo RAM - self.wram[address & 0x1FFF] = data + self.w_ram[address & 0x1FFF] = data elif (address >= 0xFF80 and address <= 0xFFFE): # FF80-FFFE High RAM - self.hram[address & 0x7F] = data + self.h_ram[address & 0x7F] = data def read(self, address): if (address >= 0xC000 and address <= 0xFDFF): # C000-DFFF Work RAM # E000-FDFF Echo RAM - return self.wram[address & 0x1FFF] & 0xFF + return self.w_ram[address & 0x1FFF] & 0xFF elif (address >= 0xFF80 and address <= 0xFFFE): # FF80-FFFE High RAM - return self.hram[address & 0x7F] & 0xFF + return self.h_ram[address & 0x7F] & 0xFF return 0xFF Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py Fri May 9 11:16:20 2008 @@ -8,41 +8,41 @@ class Channel(object): - audioIndex = 0 - audioLength = 0 - audioFrequency = 0 - - def __init__(self, sampleRate, frequencyTable): - self.sampleRate = sampleRate - self.frequencyTable = frequencyTable - self.audioLength=0 - self.audioEnvelope=0 - self.audioFrequency=0 - self.audioPlayback=0 + audio_index = 0 + audio_length = 0 + audio_frequency = 0 + + def __init__(self, sample_rate, frequency_table): + self.sample_rate = sample_rate + self.frequency_table = frequency_table + self.audio_length = 0 + self.audio_envelope = 0 + self.audio_frequency = 0 + self.audio_playback = 0 self.nr0 = 0 self.nr1 = 0 self.nr2 = 0 self.nr3 = 0 self.nr4 = 0 - self.audioIndex = 0 - self.audioLength = 0 - self.audioFrequency = 0 + self.audio_index = 0 + self.audio_length = 0 + self.audio_frequency = 0 self.enabled = False def reset(self): - self.audioIndex = 0 + self.audio_index = 0 def get_audio_length(self): - return self.audioLength + return self.audio_length def get_audio_envelope(self): - return self.audioEnvelope + return self.audio_envelope def get_audio_frequency(self): - return self.audioFrequency + return self.audio_frequency def get_audio_playback(self): - return self.audioPlayback + return self.audio_playback @@ -51,206 +51,206 @@ #SquareWaveGenerator class Channel1(Channel): # Audio Channel 1 int - def __init__(self, sampleRate, frequencyTable): - Channel.__init__(self, sampleRate, frequencyTable) - self.audioSweep=0 - self.audio1Index=0 - self.audio1Length=0 - self.audioVolume=0 - self.audio1EnvelopeLength=0 - self.audioSweepLength=0 - self.audio1Frequency=0 + def __init__(self, sample_rate, frequency_table): + Channel.__init__(self, sample_rate, frequency_table) + self.sample_sweep = 0 + self.audio_1_index = 0 + self.audio_1_length = 0 + self.audio_volume = 0 + self.audio_1_envelope_length = 0 + self.sample_sweep_length = 0 + self.audio_1_frequency = 0 # Audio Channel 1 def get_audio_sweep(self): - return self.audioSweep + return self.sample_sweep def set_audio_sweep(self, data): - self.audioSweep = data - self.audioSweepLength = (constants.SOUND_CLOCK / 128) * \ - ((self.audioSweep >> 4) & 0x07) + self.sample_sweep = data + self.sample_sweep_length = (constants.SOUND_CLOCK / 128) * \ + ((self.sample_sweep >> 4) & 0x07) def set_audio_length(self, data): - self.audioLength = data - self.audio1Length = (constants.SOUND_CLOCK / 256) * \ - (64 - (self.audioLength & 0x3F)) + self.audio_length = data + self.audio_1_length = (constants.SOUND_CLOCK / 256) * \ + (64 - (self.audio_length & 0x3F)) def set_audio_envelope(self, data): - self.audioEnvelope = data - if (self.audioPlayback & 0x40) != 0: + self.audio_envelope = data + if (self.audio_playback & 0x40) != 0: return - if (self.audioEnvelope >> 4) == 0: - self.audioVolume = 0 - elif self.audio1EnvelopeLength == 0 and \ - (self.audioEnvelope & 0x07) == 0: - self.audioVolume = (self.audioVolume + 1) & 0x0F + if (self.audio_envelope >> 4) == 0: + self.audio_volume = 0 + elif self.audio_1_envelope_length == 0 and \ + (self.audio_envelope & 0x07) == 0: + self.audio_volume = (self.audio_volume + 1) & 0x0F else: - self.audioVolume = (self.audioVolume + 2) & 0x0F + self.audio_volume = (self.audio_volume + 2) & 0x0F def set_audio_frequency(self, data): - self.audioFrequency = data - index = self.audioFrequency + ((self.audioPlayback & 0x07) << 8) - self.audio1Frequency = self.frequencyTable[index] + self.audio_frequency = data + index = self.audio_frequency + ((self.audio_playback & 0x07) << 8) + self.audio_1_frequency = self.frequency_table[index] def set_audio_playback(self, data): - self.audioPlayback = data - self.audio1Frequency = self.frequencyTable[self.audioFrequency - + ((self.audioPlayback & 0x07) << 8)] - if (self.audioPlayback & 0x80) != 0: + self.audio_playback = data + self.audio_1_frequency = self.frequency_table[self.audio_frequency + + ((self.audio_playback & 0x07) << 8)] + if (self.audio_playback & 0x80) != 0: self.enabled = True - if (self.audioPlayback & 0x40) != 0 and self.audio1Length == 0: - self.audio1Length = (constants.SOUND_CLOCK / 256) * \ - (64 - (self.audioLength & 0x3F)) - self.audioSweepLength = (constants.SOUND_CLOCK / 128) * \ - ((self.audioSweep >> 4) & 0x07) - self.audioVolume = self.audioEnvelope >> 4 - self.audio1EnvelopeLength = (constants.SOUND_CLOCK / 64) * \ - (self.audioEnvelope & 0x07) + if (self.audio_playback & 0x40) != 0 and self.audio_1_length == 0: + self.audio_1_length = (constants.SOUND_CLOCK / 256) * \ + (64 - (self.audio_length & 0x3F)) + self.sample_sweep_length = (constants.SOUND_CLOCK / 128) * \ + ((self.sample_sweep >> 4) & 0x07) + self.audio_volume = self.audio_envelope >> 4 + self.audio_1_envelope_length = (constants.SOUND_CLOCK / 64) * \ + (self.audio_envelope & 0x07) def update_audio(self): - if (self.audioPlayback & 0x40) != 0 and self.audio1Length > 0: - self.audio1Length-=1 - if self.audio1Length <= 0: + if (self.audio_playback & 0x40) != 0 and self.audio_1_length > 0: + self.audio_1_length-=1 + if self.audio_1_length <= 0: self.enabled = False - if self.audio1EnvelopeLength > 0: - self.audio1EnvelopeLength-=1 - if self.audio1EnvelopeLength <= 0: - if (self.audioEnvelope & 0x08) != 0: - if (self.audioVolume < 15): - self.audioVolume+=1 - elif self.audioVolume > 0: - self.audioVolume-=1 - self.audio1EnvelopeLength += (constants.SOUND_CLOCK / 64) * \ - (self.audioEnvelope & 0x07) - if self.audioSweepLength > 0: - self.audioSweepLength-=1 - if self.audioSweepLength <= 0: - sweepSteps = (self.audioSweep & 0x07) + if self.audio_1_envelope_length > 0: + self.audio_1_envelope_length-=1 + if self.audio_1_envelope_length <= 0: + if (self.audio_envelope & 0x08) != 0: + if (self.audio_volume < 15): + self.audio_volume+=1 + elif self.audio_volume > 0: + self.audio_volume-=1 + self.audio_1_envelope_length += (constants.SOUND_CLOCK / 64) * \ + (self.audio_envelope & 0x07) + if self.sample_sweep_length > 0: + self.sample_sweep_length-=1 + if self.sample_sweep_length <= 0: + sweepSteps = (self.sample_sweep & 0x07) if sweepSteps != 0: - frequency = ((self.audioPlayback & 0x07) << 8) + \ - self.audioFrequency - if (self.audioSweep & 0x08) != 0: + frequency = ((self.audio_playback & 0x07) << 8) + \ + self.audio_frequency + if (self.sample_sweep & 0x08) != 0: frequency -= frequency >> sweepSteps else: frequency += frequency >> sweepSteps if frequency < 2048: - self.audio1Frequency = self.frequencyTable[frequency] - self.audioFrequency = frequency & 0xFF - self.audioPlayback = (self.audioPlayback & 0xF8) + \ + self.audio_1_frequency = self.frequency_table[frequency] + self.audio_frequency = frequency & 0xFF + self.audio_playback = (self.audio_playback & 0xF8) + \ ((frequency >> 8) & 0x07) else: - self.audio1Frequency = 0 - self.outputEnable &= ~0x01 - self.audioSweepLength += (constants.SOUND_CLOCK / 128) * \ - ((self.audioSweep >> 4) & 0x07) + self.audio_1_frequency = 0 + self.output_enable &= ~0x01 + self.sample_sweep_length += (constants.SOUND_CLOCK / 128) * \ + ((self.sample_sweep >> 4) & 0x07) def mix_audio(self, buffer, length): - wavePattern = 0x18 - if (self.audioLength & 0xC0) == 0x00: - wavePattern = 0x04 - elif (self.audioLength & 0xC0) == 0x40: - wavePattern = 0x08 - elif (self.audioLength & 0xC0) == 0x80: - wavePattern = 0x10 - wavePattern << 22 + wave_patter = 0x18 + if (self.audio_length & 0xC0) == 0x00: + wave_patter = 0x04 + elif (self.audio_length & 0xC0) == 0x40: + wave_patter = 0x08 + elif (self.audio_length & 0xC0) == 0x80: + wave_patter = 0x10 + wave_patter << 22 for index in range(0, length, 3): - self.audio1Index += self.audio1Frequency - if (self.audio1Index & (0x1F << 22)) >= wavePattern: - if (self.outputTerminal & 0x10) != 0: - buffer[index + 0] -= self.audioVolume - if (self.outputTerminal & 0x01) != 0: - buffer[index + 1] -= self.audioVolume + self.audio_1_index += self.audio_1_frequency + if (self.audio_1_index & (0x1F << 22)) >= wave_patter: + if (self.output_terminal & 0x10) != 0: + buffer[index + 0] -= self.audio_volume + if (self.output_terminal & 0x01) != 0: + buffer[index + 1] -= self.audio_volume else: - if (self.outputTerminal & 0x10) != 0: - buffer[index + 0] += self.audioVolume - if (self.outputTerminal & 0x01) != 0: - buffer[index + 1] += self.audioVolume + if (self.output_terminal & 0x10) != 0: + buffer[index + 0] += self.audio_volume + if (self.output_terminal & 0x01) != 0: + buffer[index + 1] += self.audio_volume #SquareWaveGenerator class Channel2(Channel): - def __init__(self, sampleRate, frequencyTable): - Channel.__init__(self, sampleRate, frequencyTable) - self.audio2Index=0 - self.audio2Length=0 - self.audioVolume=0 - self.audio2EnvelopeLength=0 - self.audio2Frequency=0 + def __init__(self, sample_rate, frequency_table): + Channel.__init__(self, sample_rate, frequency_table) + self.audio_2_index = 0 + self.audio_2_length = 0 + self.audio_volume = 0 + self.audio_2_envelope_length = 0 + self.audio_2_frequency = 0 # Audio Channel 2 def set_audio_length(self, data): - self.audioLength = data - self.audio2Length = (constants.SOUND_CLOCK / 256) * \ - (64 - (self.audioLength & 0x3F)) + self.audio_length = data + self.audio_2_length = (constants.SOUND_CLOCK / 256) * \ + (64 - (self.audio_length & 0x3F)) def set_audio_envelope(self, data): - self.audioEnvelope = data - if (self.audioPlayback & 0x40) == 0: - if (self.audioEnvelope >> 4) == 0: - self.audioVolume = 0 - elif self.audio2EnvelopeLength == 0 and \ - (self.audioEnvelope & 0x07) == 0: - self.audioVolume = (self.audioVolume + 1) & 0x0F + self.audio_envelope = data + if (self.audio_playback & 0x40) == 0: + if (self.audio_envelope >> 4) == 0: + self.audio_volume = 0 + elif self.audio_2_envelope_length == 0 and \ + (self.audio_envelope & 0x07) == 0: + self.audio_volume = (self.audio_volume + 1) & 0x0F else: - self.audioVolume = (self.audioVolume + 2) & 0x0F + self.audio_volume = (self.audio_volume + 2) & 0x0F def set_audio_frequency(self, data): - self.audioFrequency = data - self.audio2Frequency = self.frequencyTable[self.audioFrequency\ - + ((self.audioPlayback & 0x07) << 8)] + self.audio_frequency = data + self.audio_2_frequency = self.frequency_table[self.audio_frequency\ + + ((self.audio_playback & 0x07) << 8)] def set_audio_playback(self, data): - self.audioPlayback = data - self.audio2Frequency = self.frequencyTable[self.audioFrequency\ - + ((self.audioPlayback & 0x07) << 8)] - if (self.audioPlayback & 0x80) != 0: + self.audio_playback = data + self.audio_2_frequency = self.frequency_table[self.audio_frequency\ + + ((self.audio_playback & 0x07) << 8)] + if (self.audio_playback & 0x80) != 0: self.enabled = True - if (self.audioPlayback & 0x40) != 0 and self.audio2Length == 0: - self.audio2Length = (constants.SOUND_CLOCK / 256) * \ - (64 - (self.audioLength & 0x3F)) - self.audioVolume = self.audioEnvelope >> 4 - self.audio2EnvelopeLength = (constants.SOUND_CLOCK / 64) * \ - (self.audioEnvelope & 0x07) + if (self.audio_playback & 0x40) != 0 and self.audio_2_length == 0: + self.audio_2_length = (constants.SOUND_CLOCK / 256) * \ + (64 - (self.audio_length & 0x3F)) + self.audio_volume = self.audio_envelope >> 4 + self.audio_2_envelope_length = (constants.SOUND_CLOCK / 64) * \ + (self.audio_envelope & 0x07) def update_audio(self): - if (self.audioPlayback & 0x40) != 0 and self.audio2Length > 0: - self.audio2Length-=1 - if self.audio2Length <= 0: + if (self.audio_playback & 0x40) != 0 and self.audio_2_length > 0: + self.audio_2_length-=1 + if self.audio_2_length <= 0: self.enabled = False - if self.audio2EnvelopeLength > 0: - self.audio2EnvelopeLength-=1 - if self.audio2EnvelopeLength <= 0: - if (self.audioEnvelope & 0x08) != 0: - if self.audioVolume < 15: - self.audioVolume+=1 - elif self.audioVolume > 0: - self.audioVolume-=1 - self.audio2EnvelopeLength += (constants.SOUND_CLOCK / 64) *\ - (self.audioEnvelope & 0x07) + if self.audio_2_envelope_length > 0: + self.audio_2_envelope_length-=1 + if self.audio_2_envelope_length <= 0: + if (self.audio_envelope & 0x08) != 0: + if self.audio_volume < 15: + self.audio_volume+=1 + elif self.audio_volume > 0: + self.audio_volume-=1 + self.audio_2_envelope_length += (constants.SOUND_CLOCK / 64) *\ + (self.audio_envelope & 0x07) def mix_audio(self, buffer, length): - wavePattern = 0x18 - if (self.audioLength & 0xC0) == 0x00: - wavePattern = 0x04 - elif (self.audioLength & 0xC0) == 0x40: - wavePattern = 0x08 - elif (self.audioLength & 0xC0) == 0x80: - wavePattern = 0x10 - wavePattern << 22 + wave_patter = 0x18 + if (self.audio_length & 0xC0) == 0x00: + wave_patter = 0x04 + elif (self.audio_length & 0xC0) == 0x40: + wave_patter = 0x08 + elif (self.audio_length & 0xC0) == 0x80: + wave_patter = 0x10 + wave_patter << 22 for index in range(0, length): - self.audio2Index += self.audio2Frequency - if ((self.audio2Index & (0x1F << 22)) >= wavePattern): - if ((self.outputTerminal & 0x20) != 0): - buffer[index + 0] -= self.audioVolume - if ((self.outputTerminal & 0x02) != 0): - buffer[index + 1] -= self.audioVolume + self.audio_2_index += self.audio_2_frequency + if ((self.audio_2_index & (0x1F << 22)) >= wave_patter): + if ((self.output_terminal & 0x20) != 0): + buffer[index + 0] -= self.audio_volume + if ((self.output_terminal & 0x02) != 0): + buffer[index + 1] -= self.audio_volume else: - if ((self.outputTerminal & 0x20) != 0): - buffer[index + 0] += self.audioVolume - if ((self.outputTerminal & 0x02) != 0): - buffer[index + 1] += self.audioVolume + if ((self.output_terminal & 0x20) != 0): + buffer[index + 0] += self.audio_volume + if ((self.output_terminal & 0x02) != 0): + buffer[index + 1] += self.audio_volume @@ -259,113 +259,113 @@ #SquareWaveGenerator class Channel3(Channel): - def __init__(self, sampleRate, frequencyTable): - Channel.__init__(self, sampleRate, frequencyTable) - self.audioEnable=0 - self.audioLevel=0 - self.audio3Index=0 - self.audio3Length=0 - self.audio3Frequency=0 - self.audioWavePattern = [0]*16 + def __init__(self, sample_rate, frequency_table): + Channel.__init__(self, sample_rate, frequency_table) + self.audio_enable = 0 + self.audio_level = 0 + self.audio_3_index = 0 + self.audio_3_length = 0 + self.audio_3_frequency = 0 + self.audio_wave_pattern = [0]*16 def get_audio_enable(self): - return self.audioEnable + return self.audio_enable def get_audio_level(self): - return self.audioLevel + return self.audio_level #FIXME strange number here def get_audio_4_frequency(self): - return self.audioFrequency + return self.audio_frequency def set_audio_enable(self, data): - self.audioEnable = data & 0x80 - if (self.audioEnable & 0x80) == 0: + self.audio_enable = data & 0x80 + if (self.audio_enable & 0x80) == 0: self.enabled = False def set_audio_length(self, data): - self.audioLength = data - self.audio3Length = (constants.SOUND_CLOCK / 256) * \ - (256 - self.audioLength) + self.audio_length = data + self.audio_3_length = (constants.SOUND_CLOCK / 256) * \ + (256 - self.audio_length) def set_audio_level(self, data): - self.audioLevel = data + self.audio_level = data def set_audio_frequency(self, data): - self.audioFrequency = data - index = ((self.audioPlayback & 0x07) << 8) + self.audioFrequency - self.audio3Frequency = self.frequencyTable[index] >> 1 + self.audio_frequency = data + index = ((self.audio_playback & 0x07) << 8) + self.audio_frequency + self.audio_3_frequency = self.frequency_table[index] >> 1 def set_audio_playback(self, data): - self.audioPlayback = data - index = ((self.audioPlayback & 0x07) << 8) + self.audioFrequency - self.audio3Frequency = self.frequencyTable[index] >> 1 - if (self.audioPlayback & 0x80) != 0 and (self.audioEnable & 0x80) != 0: + self.audio_playback = data + index = ((self.audio_playback & 0x07) << 8) + self.audio_frequency + self.audio_3_frequency = self.frequency_table[index] >> 1 + if (self.audio_playback & 0x80) != 0 and (self.audio_enable & 0x80) != 0: self.enabled = True - if (self.audioPlayback & 0x40) != 0 and self.audio3Length == 0: - self.audio3Length = (constants.SOUND_CLOCK / 256) *\ - (256 - self.audioLength) + if (self.audio_playback & 0x40) != 0 and self.audio_3_length == 0: + self.audio_3_length = (constants.SOUND_CLOCK / 256) *\ + (256 - self.audio_length) def set_audio_wave_pattern(self, address, data): - self.audioWavePattern[address & 0x0F] = data + self.audio_wave_pattern[address & 0x0F] = data def get_audio_wave_pattern(self, address): - return self.audioWavePattern[address & 0x0F] & 0xFF + return self.audio_wave_pattern[address & 0x0F] & 0xFF def update_audio(self): - if (self.audioPlayback & 0x40) != 0 and self.audio3Length > 0: - self.audio3Length-=1 - if self.audio3Length <= 0: - self.outputEnable &= ~0x04 + if (self.audio_playback & 0x40) != 0 and self.audio_3_length > 0: + self.audio_3_length-=1 + if self.audio_3_length <= 0: + self.output_enable &= ~0x04 def mix_audio(self, buffer, length): - wavePattern = 2 - if (self.audioLevel & 0x60) == 0x00: - wavePattern = 8 - elif (self.audioLevel & 0x60) == 0x40: - wavePattern = 0 - elif (self.audioLevel & 0x60) == 0x80: - wavePattern = 1 + wave_patter = 2 + if (self.audio_level & 0x60) == 0x00: + wave_patter = 8 + elif (self.audio_level & 0x60) == 0x40: + wave_patter = 0 + elif (self.audio_level & 0x60) == 0x80: + wave_patter = 1 for index in range(0, length, 2): - self.audio3Index += self.audio3Frequency - sample = self.audioWavePattern[(self.audio3Index >> 23) & 0x0F] - if ((self.audio3Index & (1 << 22)) != 0): + self.audio_3_index += self.audio_3_frequency + sample = self.audio_wave_pattern[(self.audio_3_index >> 23) & 0x0F] + if ((self.audio_3_index & (1 << 22)) != 0): sample = (sample >> 0) & 0x0F else: sample = (sample >> 4) & 0x0F sample = ((sample - 8) << 1) >> level - if (self.outputTerminal & 0x40) != 0: + if (self.output_terminal & 0x40) != 0: buffer[index + 0] += sample - if (self.outputTerminal & 0x04) != 0: + if (self.output_terminal & 0x04) != 0: buffer[index + 1] += sample class NoiseGenerator(Channel): - def __init__(self, sampleRate, frequencyTable): - Channel.__init__(self, sampleRate, frequencyTable) + def __init__(self, sample_rate, frequency_table): + Channel.__init__(self, sample_rate, frequency_table) # Audio Channel 4 int - self.audioLength=0 - self.audioPolynomial=0 - self.audio4Index=0 - self.audio4Length=0 - self.audioVolume=0 - self.audio4EnvelopeLength=0 - self.audio4Frequency=0 + self.audio_length = 0 + self.audio_polynomial = 0 + self.audio_4_index = 0 + self.audio_4_length = 0 + self.audio_volume = 0 + self.audio_4_envelope_length = 0 + self.audio_4_frequency = 0 self.generate_noise_frequency_ratio_table() self.generate_noise_tables() def generate_noise_frequency_ratio_table(self): # Polynomial Noise Frequency Ratios - # 4194304 Hz * 1/2^3 * 2 4194304 Hz * 1/2^3 * 1 4194304 Hz * 1/2^3 * - # 1/2 4194304 Hz * 1/2^3 * 1/3 4194304 Hz * 1/2^3 * 1/4 4194304 Hz * - # 1/2^3 * 1/5 4194304 Hz * 1/2^3 * 1/6 4194304 Hz * 1/2^3 * 1/7 + # 4194304 Hz * 1 / 2^3 * 2 4194304 Hz * 1 / 2^3 * 1 4194304 Hz * 1 / 2^3 * + # 1 / 2 4194304 Hz * 1 / 2^3 * 1 / 3 4194304 Hz * 1 / 2^3 * 1 / 4 4194304 Hz * + # 1 / 2^3 * 1 / 5 4194304 Hz * 1 / 2^3 * 1 / 6 4194304 Hz * 1 / 2^3 * 1 / 7 self.noiseFreqRatioTable = [0] * 8 - sampleFactor = ((1 << 16) / self.sampleRate) + sampleFactor = ((1 << 16) / self.sample_rate) for ratio in range(0, 8): divider = 1 if ratio != 0: @@ -379,115 +379,115 @@ def create_7_step_noise_table(self): # Noise Tables - self. noiseStep7Table = [0]*4 + self. noise_step_7_table = [0]*4 polynomial = 0x7F # 7 steps for index in range(0, 0x7F): polynomial = (((polynomial << 6) ^ (polynomial << 5)) & 0x40) | \ (polynomial >> 1) if (index & 31) == 0: - self.noiseStep7Table[index >> 5] = 0 - self.noiseStep7Table[index >> 5] |= (polynomial & 1) << \ + self.noise_step_7_table[index >> 5] = 0 + self.noise_step_7_table[index >> 5] |= (polynomial & 1) << \ (index & 31) def create_15_step_noise_table(self): # 15 steps& - self.noiseStep15Table = [0]*1024 + self.noise_step_15_table = [0]*1024 polynomial = 0x7FFF for index in range(0, 0x7FFF): polynomial = (((polynomial << 14) ^ (polynomial << 13)) & \ 0x4000) | (polynomial >> 1) if (index & 31) == 0: - self.noiseStep15Table[index >> 5] = 0 - self.noiseStep15Table[index >> 5] |= (polynomial & 1) << \ + self.noise_step_15_table[index >> 5] = 0 + self.noise_step_15_table[index >> 5] |= (polynomial & 1) << \ (index & 31) # Audio Channel 4 def get_audio_length(self): - return self.audioLength + return self.audio_length def get_audio_polynomial(self): - return self.audioPolynomial + return self.audio_polynomial def get_audio_playback(self): - return self.audioPlayback + return self.audio_playback def set_audio_length(self, data): - self.audioLength = data - self.audio4Length = (constants.SOUND_CLOCK / 256) * \ - (64 - (self.audioLength & 0x3F)) + self.audio_length = data + self.audio_4_length = (constants.SOUND_CLOCK / 256) * \ + (64 - (self.audio_length & 0x3F)) def set_audio_envelope(self, data): - self.audioEnvelope = data - if (self.audioPlayback & 0x40) == 0: - if (self.audioEnvelope >> 4) == 0: - self.audioVolume = 0 - elif self.audio4EnvelopeLength == 0 and \ - (self.audioEnvelope & 0x07) == 0: - self.audioVolume = (self.audioVolume + 1) & 0x0F + self.audio_envelope = data + if (self.audio_playback & 0x40) == 0: + if (self.audio_envelope >> 4) == 0: + self.audio_volume = 0 + elif self.audio_4_envelope_length == 0 and \ + (self.audio_envelope & 0x07) == 0: + self.audio_volume = (self.audio_volume + 1) & 0x0F else: - self.audioVolume = (self.audioVolume + 2) & 0x0F + self.audio_volume = (self.audio_volume + 2) & 0x0F def set_audio_polynomial(self, data): - self.audioPolynomial = data - if (self.audioPolynomial >> 4) <= 12: - freq = self.noiseFreqRatioTable[self.audioPolynomial & 0x07] - self.audio4Frequency = freq >> ((self.audioPolynomial >> 4) + 1) + self.audio_polynomial = data + if (self.audio_polynomial >> 4) <= 12: + freq = self.noiseFreqRatioTable[self.audio_polynomial & 0x07] + self.audio_4_frequency = freq >> ((self.audio_polynomial >> 4) + 1) else: - self.audio4Frequency = 0 + self.audio_4_frequency = 0 def set_audio_playback(self, data): - self.audioPlayback = data - if (self.audioPlayback & 0x80) != 0: + self.audio_playback = data + if (self.audio_playback & 0x80) != 0: self.enabled = True - if (self.audioPlayback & 0x40) != 0 and self.audio4Length == 0: - self.audio4Length = (constants.SOUND_CLOCK / 256) * \ - (64 - (self.audioLength & 0x3F)) - self.audioVolume = self.audioEnvelope >> 4 - self.audio4EnvelopeLength = (constants.SOUND_CLOCK / 64) * \ - (self.audioEnvelope & 0x07) - self.audio4Index = 0 + if (self.audio_playback & 0x40) != 0 and self.audio_4_length == 0: + self.audio_4_length = (constants.SOUND_CLOCK / 256) * \ + (64 - (self.audio_length & 0x3F)) + self.audio_volume = self.audio_envelope >> 4 + self.audio_4_envelope_length = (constants.SOUND_CLOCK / 64) * \ + (self.audio_envelope & 0x07) + self.audio_4_index = 0 def update_audio(self): - if (self.audioPlayback & 0x40) != 0 and self.audio4Length > 0: - self.audio4Length-=1 - if self.audio4Length <= 0: - self.outputEnable &= ~0x08 - if self.audio4EnvelopeLength > 0: - self.audio4EnvelopeLength-=1 - if self.audio4EnvelopeLength <= 0: - if (self.audioEnvelope & 0x08) != 0: - if self.audioVolume < 15: - self.audioVolume+=1 - elif self.audioVolume > 0: - self.audioVolume-=1 - self.audio4EnvelopeLength += (constants.SOUND_CLOCK / 64) *\ - (self.audioEnvelope & 0x07) + if (self.audio_playback & 0x40) != 0 and self.audio_4_length > 0: + self.audio_4_length-=1 + if self.audio_4_length <= 0: + self.output_enable &= ~0x08 + if self.audio_4_envelope_length > 0: + self.audio_4_envelope_length-=1 + if self.audio_4_envelope_length <= 0: + if (self.audio_envelope & 0x08) != 0: + if self.audio_volume < 15: + self.audio_volume+=1 + elif self.audio_volume > 0: + self.audio_volume-=1 + self.audio_4_envelope_length += (constants.SOUND_CLOCK / 64) *\ + (self.audio_envelope & 0x07) def mix_audio(self, buffer, length): for index in range(0, length, 2): - self.audio4Index += self.audio4Frequency + self.audio_4_index += self.audio_4_frequency polynomial - if (self.audioPolynomial & 0x08) != 0: + if (self.audio_polynomial & 0x08) != 0: # 7 steps - self.audio4Index &= 0x7FFFFF - polynomial = self.noiseStep7Table[self.audio4Index >> 21] >>\ - ((self.audio4Index >> 16) & 31) + self.audio_4_index &= 0x7FFFFF + polynomial = self.noise_step_7_table[self.audio_4_index >> 21] >>\ + ((self.audio_4_index >> 16) & 31) else: # 15 steps - self.audio4Index &= 0x7FFFFFFF - polynomial = self.noiseStep15Table[self.audio4Index >> 21] >> \ - ((self.audio4Index >> 16) & 31) + self.audio_4_index &= 0x7FFFFFFF + polynomial = self.noise_step_15_table[self.audio_4_index >> 21] >> \ + ((self.audio_4_index >> 16) & 31) if (polynomial & 1) != 0: - if (self.outputTerminal & 0x80) != 0: - buffer[index + 0] -= self.audioVolume - if (self.outputTerminal & 0x08) != 0: - buffer[index + 1] -= self.audioVolume + if (self.output_terminal & 0x80) != 0: + buffer[index + 0] -= self.audio_volume + if (self.output_terminal & 0x08) != 0: + buffer[index + 1] -= self.audio_volume else: - if (self.outputTerminal & 0x80) != 0: - buffer[index + 0] += self.audioVolume - if (self.outputTerminal & 0x08) != 0: - buffer[index + 1] += self.audioVolume + if (self.output_terminal & 0x80) != 0: + buffer[index + 0] += self.audio_volume + if (self.output_terminal & 0x08) != 0: + buffer[index + 1] += self.audio_volume @@ -496,14 +496,14 @@ class Sound(object): - def __init__(self, soundDriver): - self.buffer = [0]*512 - self.outputLevel=0 - self.outputTerminal=0 - self.outputEnable=0 + def __init__(self, sound_driver): + self.buffer = [0] * 512 + self.outputLevel = 0 + self.output_terminal = 0 + self.output_enable = 0 - self.driver = soundDriver - self.sampleRate = self.driver.get_sample_rate() + self.driver = sound_driver + self.sample_rate = self.driver.get_sample_rate() self.generate_frequency_table() self.create_audio_channels() @@ -511,22 +511,22 @@ self.reset() def create_audio_channels(self): - self.channel1 = Channel1(self.sampleRate, self.frequencyTable) - self.channel2 = Channel2(self.sampleRate, self.frequencyTable) - self.channel3 = Channel3(self.sampleRate, self.frequencyTable) - self.channel4 = NoiseGenerator(self.sampleRate, self.frequencyTable) + self.channel1 = Channel1(self.sample_rate, self.frequency_table) + self.channel2 = Channel2(self.sample_rate, self.frequency_table) + self.channel3 = Channel3(self.sample_rate, self.frequency_table) + self.channel4 = NoiseGenerator(self.sample_rate, self.frequency_table) def generate_frequency_table(self): - self.frequencyTable = [0] * 2048 + self.frequency_table = [0] * 2048 # frequency = (4194304 / 32) / (2048 - period) Hz for period in range(0, 2048): skip = (((constants.GAMEBOY_CLOCK << 10) / \ - self.sampleRate) << 16) / (2048 - period) + self.sample_rate) << 16) / (2048 - period) if skip >= (32 << 22): - self.frequencyTable[period] = 0 + self.frequency_table[period] = 0 else: - self.frequencyTable[period] = skip + self.frequency_table[period] = skip def reset(self): self.cycles = constants.GAMEBOY_CLOCK / constants.SOUND_CLOCK @@ -536,10 +536,10 @@ self.channel3.reset() self.channel4.reset() - self.channel1.audioIndex = 0 - self.channel2.audioIndex = 0 - self.channel3.audioIndex = 0 - self.channel4.audioIndex = 0 + self.channel1.audio_index = 0 + self.channel2.audio_index = 0 + self.channel3.audio_index = 0 + self.channel4.audio_index = 0 self.write(constants.NR10, 0x80) self.write(constants.NR11, 0x3F) # 0xBF @@ -703,27 +703,27 @@ self.channel3.set_audio_wave_pattern(address, data) def update_audio(self): - if (self.outputEnable & 0x80) == 0: + if (self.output_enable & 0x80) == 0: return - if (self.outputEnable & 0x01) != 0: + if (self.output_enable & 0x01) != 0: self.channel1.update_audio() - if (self.outputEnable & 0x02) != 0: + if (self.output_enable & 0x02) != 0: self.channel2.update_audio() - if (self.outputEnable & 0x04) != 0: + if (self.output_enable & 0x04) != 0: self.channel3.update_audio() - if (self.outputEnable & 0x08) != 0: + if (self.output_enable & 0x08) != 0: self.channel4.update_audio() def mix_audio(self, buffer, length): - if (self.outputEnable & 0x80) == 0: + if (self.output_enable & 0x80) == 0: return - if (self.outputEnable & 0x01) != 0: + if (self.output_enable & 0x01) != 0: self.channel1.mix_audio(buffer, length) - if (self.outputEnable & 0x02) != 0: + if (self.output_enable & 0x02) != 0: self.channel2.mix_audio(buffer, length) - if (self.outputEnable & 0x04) != 0: + if (self.output_enable & 0x04) != 0: self.channel3.mix_audio(buffer, length) - if (self.outputEnable & 0x08) != 0: + if (self.output_enable & 0x08) != 0: self.channel4.mix_audio(buffer, length) # Output Control @@ -731,21 +731,21 @@ return self.outputLevel def get_output_terminal(self): - return self.outputTerminal + return self.output_terminal def get_output_enable(self): - return self.outputEnable + return self.output_enable def set_output_level(self, data): self.outputLevel = data def set_output_terminal(self, data): - self.outputTerminal = data + self.output_terminal = data def set_output_enable(self, data): - self.outputEnable = (self.outputEnable & 0x7F) | (data & 0x80) - if (self.outputEnable & 0x80) == 0x00: - self.outputEnable &= 0xF0 + self.output_enable = (self.output_enable & 0x7F) | (data & 0x80) + if (self.output_enable & 0x80) == 0x00: + self.output_enable &= 0xF0 # SOUND DRIVER ----------------------------------------------------------------- @@ -755,21 +755,21 @@ def __init__(self): self.enabled = True - self.sampleRate = 44100 - self.channelCount = 2 - self.bitsPerSample = 8 + self.sample_rate = 44100 + self.channel_count = 2 + self.bits_per_sample = 8 def is_enabled(self): return self.enabled def get_sample_rate(self): - return self.sampleRate + return self.sample_rate def get_channels(self): - return self.channelCount + return self.channel_count def get_bits_per_sample(self): - return self.bitsPerSample + return self.bits_per_sample def start(self): pass Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cpu.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cpu.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cpu.py Fri May 9 11:16:20 2008 @@ -220,22 +220,22 @@ assert cpu.pc.get() == pc, "Register pc is %s but should be %s" % (hex(cpu.pc.get()), hex(pc)) -def assert_default_flags(cpu, zFlag=True, nFlag=False, hFlag=False, cFlag=False, pFlag=False, sFlag=False): - assert_flags(cpu, zFlag, nFlag, hFlag, cFlag, pFlag, sFlag) +def assert_default_flags(cpu, z_flag=True, n_flag=False, h_flag=False, c_flag=False, p_flag=False, s_flag=False): + assert_flags(cpu, z_flag, n_flag, h_flag, c_flag, p_flag, s_flag) -def assert_flags(cpu, zFlag=None, nFlag=None, hFlag=None, cFlag=None, pFlag=None, sFlag=None): - if zFlag is not None: - assert cpu.f.zFlag == zFlag, "Z-Flag is %s but should be %s" % (cpu.f.zFlag, zFlag) - if nFlag is not None: - assert cpu.f.nFlag == nFlag, "N-Flag is %s but should be %s" % (cpu.f.nFlag, nFlag) - if hFlag is not None: - assert cpu.f.hFlag == hFlag, "H-Flag is %s but should be %s" % (cpu.f.hFlag, hFlag) - if cFlag is not None: - assert cpu.f.cFlag == cFlag, "C-Flag is %s but should be %s" % (cpu.f.cFlag, cFlag) - if pFlag is not None: - assert cpu.f.pFlag == pFlag, "P-Flag is %s but should be %s" % (cpu.f.pFlag, pFlag) - if sFlag is not None: - assert cpu.f.sFlag == sFlag, "S-Flag is %s but should be %s" % (cpu.f.sFlag, sFlag) +def assert_flags(cpu, z_flag=None, n_flag=None, h_flag=None, c_flag=None, p_flag=None, s_flag=None): + if z_flag is not None: + assert cpu.f.z_flag == z_flag, "Z-Flag is %s but should be %s" % (cpu.f.z_flag, z_flag) + if n_flag is not None: + assert cpu.f.n_flag == n_flag, "N-Flag is %s but should be %s" % (cpu.f.n_flag, n_flag) + if h_flag is not None: + assert cpu.f.h_flag == h_flag, "H-Flag is %s but should be %s" % (cpu.f.h_flag, h_flag) + if c_flag is not None: + assert cpu.f.c_flag == c_flag, "C-Flag is %s but should be %s" % (cpu.f.c_flag, c_flag) + if p_flag is not None: + assert cpu.f.p_flag == p_flag, "P-Flag is %s but should be %s" % (cpu.f.p_flag, p_flag) + if s_flag is not None: + assert cpu.f.s_flag == s_flag, "S-Flag is %s but should be %s" % (cpu.f.s_flag, s_flag) def prepare_for_fetch(cpu, value, valueLo=None): pc = cpu.pc.get() @@ -494,17 +494,17 @@ # cycle testing is done in the other tests a = cpu.a a.set(0xFF) - cpu.f.cFlag = True + cpu.f.c_flag = True cpu.inc(a.get, a.set) - assert_default_flags(cpu, zFlag=True, hFlag=True, cFlag=True) + assert_default_flags(cpu, z_flag=True, h_flag=True, c_flag=True) a.set(0x01) cpu.inc(a.get, a.set) - assert_default_flags(cpu, zFlag=False, hFlag=False, cFlag=True) + assert_default_flags(cpu, z_flag=False, h_flag=False, c_flag=True) a.set(0x0F) cpu.inc(a.get, a.set) - assert_default_flags(cpu, zFlag=False, hFlag=True, cFlag=True) + assert_default_flags(cpu, z_flag=False, h_flag=True, c_flag=True) # inc_B C D E H L A def test_0x04_to_0x3C_inc_registers(): @@ -540,13 +540,13 @@ # cycle testing is done in the other tests a = cpu.a a.set(1) - cpu.f.cFlag = True + cpu.f.c_flag = True cpu.dec(a.get, a.set) - assert_default_flags(cpu, zFlag=True, hFlag=False, nFlag=True, cFlag=True) + assert_default_flags(cpu, z_flag=True, h_flag=False, n_flag=True, c_flag=True) a.set(0x0F+1) cpu.dec(a.get, a.set) - assert_default_flags(cpu, zFlag=False, hFlag=True, nFlag=True, cFlag=True) + assert_default_flags(cpu, z_flag=False, h_flag=True, n_flag=True, c_flag=True) # dec_B C D E H L A @@ -616,14 +616,14 @@ cpu.a.set(value) cycle_test(cpu, 0x07, 1) assert_default_registers(cpu, a=((value << 1) | (value >> 7)) & 0xFF, f=None); - assert_default_flags(cpu, zFlag=False, cFlag=False) + assert_default_flags(cpu, z_flag=False, c_flag=False) cpu.reset() value = 0x40 cpu.a.set(value) cycle_test(cpu, 0x07, 1) assert_default_registers(cpu, a=((value << 1) | (value >> 7)) & 0xFF, f=None); - assert_default_flags(cpu, zFlag=False, cFlag=True) + assert_default_flags(cpu, z_flag=False, c_flag=True) # rrca def test_0x0F(): @@ -632,66 +632,66 @@ cpu.a.set(value) cycle_test(cpu, 0x0F, 1) assert_default_registers(cpu, a=((value >> 1) | (value << 7)) & 0xFF, f=None); - assert_default_flags(cpu, zFlag=False, cFlag=False) + assert_default_flags(cpu, z_flag=False, c_flag=False) cpu.reset() value = 0x02 cpu.a.set(value) cycle_test(cpu, 0x0F, 1) assert_default_registers(cpu, a=((value >> 1) | (value << 7)) & 0xFF, f=None); - assert_default_flags(cpu, zFlag=False, cFlag=True) + assert_default_flags(cpu, z_flag=False, c_flag=True) # rla def test_0x17(): cpu = get_cpu() value = 0x01 cpu.a.set(value) - cpu.f.cFlag = False + cpu.f.c_flag = False cycle_test(cpu, 0x17, 1) assert_default_registers(cpu, a=(value << 1) & 0xFF, f=None); - assert_default_flags(cpu, zFlag=False, cFlag=False) + assert_default_flags(cpu, z_flag=False, c_flag=False) cpu.reset() value = 0x01 cpu.a.set(value) - cpu.f.cFlag = True + cpu.f.c_flag = True cycle_test(cpu, 0x17, 1) assert_default_registers(cpu, a=((value << 1)+1) & 0xFF, f=None); - assert_default_flags(cpu, zFlag=False, cFlag=False) + assert_default_flags(cpu, z_flag=False, c_flag=False) cpu.reset() value = 0x40 cpu.a.set(value) - cpu.f.cFlag = False + cpu.f.c_flag = False cycle_test(cpu, 0x17, 1) assert_default_registers(cpu, a=(value << 1) & 0xFF, f=None); - assert_default_flags(cpu, zFlag=False, cFlag=True) + assert_default_flags(cpu, z_flag=False, c_flag=True) # rra def test_0x1F(): cpu = get_cpu() value = 0x40 cpu.a.set(value) - cpu.f.cFlag = False + cpu.f.c_flag = False cycle_test(cpu, 0x1F, 1) assert_default_registers(cpu, a=(value >> 1) & 0xFF, f=None); - assert_default_flags(cpu, zFlag=False, cFlag=False) + assert_default_flags(cpu, z_flag=False, c_flag=False) cpu.reset() value = 0x40 cpu.a.set(value) - cpu.f.cFlag = True + cpu.f.c_flag = True cycle_test(cpu, 0x1F, 1) assert_default_registers(cpu, a=(0x08+(value >> 1)) & 0xFF, f=None); - assert_default_flags(cpu, zFlag=False, cFlag=False) + assert_default_flags(cpu, z_flag=False, c_flag=False) cpu.reset() value = 0x02 cpu.a.set(value) - cpu.f.cFlag = False + cpu.f.c_flag = False cycle_test(cpu, 0x1F, 1) assert_default_registers(cpu, a=(value >> 1) & 0xFF, f=None); - assert_default_flags(cpu, zFlag=False, cFlag=True) + assert_default_flags(cpu, z_flag=False, c_flag=True) # daa def test_0x27(): @@ -703,38 +703,38 @@ cpu = get_cpu() value = 0x12 fValue = cpu.f.get() - cpu.f.nFlag = False - cpu.f.hFlag = False + cpu.f.n_flag = False + cpu.f.h_flag = False cpu.a.set(value) cycle_test(cpu, 0x2F, 1) assert_default_registers(cpu, a=value^0xFF, f=None) - assert_default_flags(cpu, nFlag=True, hFlag=True) + assert_default_flags(cpu, n_flag=True, h_flag=True) # scf def test_0x37(): cpu = get_cpu() - cpu.f.cFlag = False + cpu.f.c_flag = False cycle_test(cpu, 0x37, 0) assert_default_registers(cpu, f=None) - assert_default_flags(cpu, cFlag=True) + assert_default_flags(cpu, c_flag=True) - cpu.f.cFlag = True + cpu.f.c_flag = True cycle_test(cpu, 0x37, 0) assert_default_registers(cpu, f=None) - assert_default_flags(cpu, cFlag=True) + assert_default_flags(cpu, c_flag=True) # ccf def test_0x3F(): cpu = get_cpu() - cpu.f.cFlag = True + cpu.f.c_flag = True cycle_test(cpu, 0x3F, 0) assert_default_registers(cpu, f=None) - assert_default_flags(cpu, cFlag=False) + assert_default_flags(cpu, c_flag=False) - cpu.f.cFlag = False + cpu.f.c_flag = False cycle_test(cpu, 0x3F, 0) assert_default_registers(cpu, f=None) - assert_default_flags(cpu, cFlag=True) + assert_default_flags(cpu, c_flag=True) # halt def test_0x76(): @@ -775,13 +775,13 @@ cpu.a.set(0) cpu.b.set(0) cpu.add_a(cpu.b.get, cpu.b.set) - assert_default_flags(cpu, zFlag=True, hFlag=False) + assert_default_flags(cpu, z_flag=True, h_flag=False) cpu.reset() cpu.a.set(0x0F) cpu.b.set(0x01) cpu.add_a(cpu.b.get, cpu.b.set) - assert_default_flags(cpu, zFlag=False, hFlag=True) + assert_default_flags(cpu, z_flag=False, h_flag=True) # add_A_B to add_A_A @@ -817,15 +817,15 @@ b.set(0) cpu.add_with_carry(b.get, b.set) assert_default_registers(cpu, a=0, f=None) - assert_default_flags(cpu, zFlag=True, cFlag=False, hFlag=False) + assert_default_flags(cpu, z_flag=True, c_flag=False, h_flag=False) cpu.reset() a.set(0) b.set(0) - cpu.f.cFlag = True + cpu.f.c_flag = True cpu.add_with_carry(b.get, b.set) assert_default_registers(cpu, a=1, f=None) - assert_default_flags(cpu, zFlag=False, cFlag=False, hFlag=False) + assert_default_flags(cpu, z_flag=False, c_flag=False, h_flag=False) cpu.reset() a.set(0xF0) @@ -833,14 +833,14 @@ cpu.add_with_carry(b.get, b.set) # overflow for a assert_default_registers(cpu, a=0xEF, bc=None, f=None) - assert_default_flags(cpu, zFlag=False, cFlag=True, hFlag=False) + assert_default_flags(cpu, z_flag=False, c_flag=True, h_flag=False) cpu.reset() a.set(0x0F) b.set(0x01) cpu.add_with_carry(b.get, b.set) assert_default_registers(cpu, a=0x10, f=None, bc=None) - assert_default_flags(cpu, zFlag=False, cFlag=False, hFlag=True) + assert_default_flags(cpu, z_flag=False, c_flag=False, h_flag=True) # adc_A_B to adx_A_A def test_0x88_to_0x8F(): @@ -859,7 +859,7 @@ assert cpu.a.get() == 2*value cpu.reset() - cpu.f.cFlag = True + cpu.f.c_flag = True cpu.a.set(value-1) register.set(value) numCycles= 1 @@ -903,15 +903,15 @@ b.set(value) cpu.subtract_with_carry(b.get, b.set) assert_default_registers(cpu, a=0, bc=None, f=None) - assert_default_flags(cpu, zFlag=True, cFlag=False, hFlag=False, nFlag=True) + assert_default_flags(cpu, z_flag=True, c_flag=False, h_flag=False, n_flag=True) cpu.reset() a.set(value) b.set(value-1) - cpu.f.cFlag = True + cpu.f.c_flag = True cpu.subtract_with_carry(b.get, b.set) assert_default_registers(cpu, a=0, bc=None, f=None) - assert_default_flags(cpu, zFlag=True, cFlag=False, hFlag=False, nFlag=True) + assert_default_flags(cpu, z_flag=True, c_flag=False, h_flag=False, n_flag=True) cpu.reset() a.set(0x20) @@ -919,7 +919,7 @@ cpu.subtract_with_carry(b.get, b.set) # overflow for a assert_default_registers(cpu, a=0x1F, bc=None, f=None) - assert_default_flags(cpu, zFlag=False, cFlag=False, hFlag=True, nFlag=True) + assert_default_flags(cpu, z_flag=False, c_flag=False, h_flag=True, n_flag=True) # sbc_A_B to sbc_A_A @@ -939,7 +939,7 @@ assert cpu.a.get() == 0 cpu.reset() - cpu.f.cFlag = True + cpu.f.c_flag = True cpu.a.set(value+1) register.set(value) numCycles= 1 @@ -960,13 +960,13 @@ cpu.a.set(value) cpu.b.set(value) cpu.AND(cpu.b.get, cpu.b.set) - assert_default_flags(cpu, zFlag=False) + assert_default_flags(cpu, z_flag=False) cpu.reset() cpu.a.set(value) cpu.b.set(0) cpu.AND(cpu.b.get, cpu.b.set) - assert_default_flags(cpu, zFlag=True) + assert_default_flags(cpu, z_flag=True) # and_A_B to and_A_A def test_0xA0_to_0xA7(): @@ -1001,13 +1001,13 @@ cpu.a.set(value) cpu.b.set(value) cpu.XOR(cpu.b.get, cpu.b.set) - assert_default_flags(cpu, zFlag=True) + assert_default_flags(cpu, z_flag=True) cpu.reset() cpu.a.set(value) cpu.b.set(value+1) cpu.XOR(cpu.b.get, cpu.b.set) - assert_default_flags(cpu, zFlag=False) + assert_default_flags(cpu, z_flag=False) # xor_A_B to xor_A_A def test_0xA8_to_0xAF(): @@ -1029,7 +1029,7 @@ else: assert cpu.a.get() == (valueA ^ value) if cpu.a.get() == 0: - assert cpu.f.zFlag == True + assert cpu.f.z_flag == True else: assert cpu.f.get() == 0 value += 1 @@ -1041,13 +1041,13 @@ cpu.a.set(value) cpu.b.set(value) cpu.OR(cpu.b.get, cpu.b.set) - assert_default_flags(cpu, zFlag=False) + assert_default_flags(cpu, z_flag=False) cpu.reset() cpu.a.set(0) cpu.b.set(0) cpu.OR(cpu.b.get, cpu.b.set) - assert_default_flags(cpu, zFlag=True) + assert_default_flags(cpu, z_flag=True) # or_A_B to or_A_A def test_0xB0_to_0xB7(): @@ -1081,19 +1081,19 @@ cpu.a.set(value) cpu.b.set(value) cpu.compare_a(cpu.b.get, cpu.b.set) - assert_default_flags(cpu, zFlag=True, nFlag=True) + assert_default_flags(cpu, z_flag=True, n_flag=True) cpu.reset() cpu.a.set(value) cpu.b.set(0) cpu.compare_a(cpu.b.get, cpu.b.set) - assert_default_flags(cpu, zFlag=False, nFlag=True) + assert_default_flags(cpu, z_flag=False, n_flag=True) cpu.reset() cpu.a.set(0xF0) cpu.b.set(0x01) cpu.compare_a(cpu.b.get, cpu.b.set) - assert_default_flags(cpu, zFlag=False, hFlag=True, nFlag=True) + assert_default_flags(cpu, z_flag=False, h_flag=True, n_flag=True) # cp_A_B to cp_A_A @@ -1256,7 +1256,7 @@ cpu.reset() cpu.halted = True cpu.interrupt.set_interrupt_enable() - cpu.interrupt.vBlank.set_pending() + cpu.interrupt.v_blank.set_pending() assert cpu.interrupt.is_pending() == True cpu.cycles = 4 cpu.handle_pending_interrupt() @@ -1270,14 +1270,14 @@ cpu.sp.set(0x02) sp = cpu.sp.get() cpu.interrupt.set_interrupt_enable() - cpu.interrupt.vBlank.set_pending() + cpu.interrupt.v_blank.set_pending() cpu.interrupt.lcd.set_pending() assert cpu.interrupt.is_pending() == True cpu.cycles = 0 cpu.handle_pending_interrupt() assert cpu.cycles == 0 assert cpu.halted == False - assert_default_registers(cpu, pc=cpu.interrupt.vBlank.callCode, sp=sp-2) + assert_default_registers(cpu, pc=cpu.interrupt.v_blank.call_code, sp=sp-2) assert cpu.pop() == 0x34 assert cpu.pop() == 0x12 @@ -1371,7 +1371,7 @@ cpu.ime = True cpu.halted = False prepare_for_fetch(cpu, 0x00) # nop 1 cycle - cpu.interrupt.vBlank.set_pending() + cpu.interrupt.v_blank.set_pending() cpu.interrupt.serial.set_pending() cpu.interrupt.set_interrupt_enable(True) assert cpu.interrupt.is_pending() == True @@ -1379,8 +1379,8 @@ assert cpu.ime == True cycle_test(cpu, 0xFB, 1+1) assert cpu.interrupt.is_pending() == False - assert cpu.interrupt.vBlank.is_pending() == False - assert cpu.pc.get() == cpu.interrupt.vBlank.callCode + assert cpu.interrupt.v_blank.is_pending() == False + assert cpu.pc.get() == cpu.interrupt.v_blank.call_code assert cpu.ime == False def conditionalCallTest(cpu, opCode, flagSetter): @@ -1405,7 +1405,7 @@ conditionalCallTest(cpu, 0xC4, setFlag0xC4) def setFlag0xC4(cpu, value): - cpu.f.zFlag = not value + cpu.f.z_flag = not value # call_Z_nnnn def test_0xCC(): @@ -1413,7 +1413,7 @@ conditionalCallTest(cpu, 0xCC, setFlag0xC4) def setFlag0xCC(cpu, value): - cpu.f.cFlag = not value + cpu.f.c_flag = not value # call_NC_nnnn def test_0xD4(): @@ -1421,7 +1421,7 @@ conditionalCallTest(cpu, 0xD4, setFlag0xC4) def setFlag0xD4(cpu, value): - cpu.f.cFlag = value + cpu.f.c_flag = value # call_C_nnnn def test_0xDC(): @@ -1429,7 +1429,7 @@ conditionalCallTest(cpu, 0xDC, setFlag0xC4) def setFlag0xDC(cpu, value): - cpu.f.zFlag = value + cpu.f.z_flag = value # push_BC to push_AF def test_0xC5_to_0xF5(): @@ -1508,7 +1508,7 @@ cycle_test(cpu, 0xFE, 2) assert_default_registers(cpu, a=valueA, pc=pc+1, f=cpu.f.get()) - assert cpu.f.zFlag == True + assert cpu.f.z_flag == True # rst(0x00) to rst(0x38) def test_0xC7_to_0xFF(): @@ -1539,13 +1539,13 @@ a = cpu.a a.set(0x01) cpu.rotate_left_a() - assert_default_flags(cpu, zFlag=False, cFlag=False) + assert_default_flags(cpu, z_flag=False, c_flag=False) assert_default_registers(cpu, a=0x02, f=None) cpu.reset() a.set(0x40) cpu.rotate_left_a() - assert_default_flags(cpu, zFlag=False, cFlag=True) + assert_default_flags(cpu, z_flag=False, c_flag=True) assert_default_registers(cpu, a=0x80, f=None) @@ -1613,12 +1613,12 @@ cpu.reset() register.set(0) fetch_execute_cycle_test_second_order(cpu, registerOpCode, cycles) - assert cpu.f.zFlag == True + assert cpu.f.z_flag == True cpu.reset() register.set((1< 0: + self.divider_cycles -= ticks + if self.divider_cycles > 0: return - count = int(ceil(-1.0*self.dividerCycles / constants.DIV_CLOCK)) + count = int(ceil(-1.0*self.divider_cycles / constants.DIV_CLOCK)) self.div = (self.div + count) & 0xFF - self.dividerCycles += constants.DIV_CLOCK*count + self.divider_cycles += constants.DIV_CLOCK*count def emulate_timer(self, ticks): if (self.tac & 0x04) == 0: return - self.timerCycles -= ticks - if self.timerCycles > 0: + self.timer_cycles -= ticks + if self.timer_cycles > 0: return - count = int(ceil(-1.0*self.timerCycles / self.timerClock)) - self.tima_tero_pass_check(count) + count = int(ceil(-1.0*self.timer_cycles / self.timer_clock)) + self.tima_zero_pass_check(count) self.tima = (self.tima + count) & 0xFF - self.timerCycles += self.timerClock * count + self.timer_cycles += self.timer_clock * count - def tima_tero_pass_check(self, count): + def tima_zero_pass_check(self, count): if (self.tima < 0) and (self.tima + count >= 0): self.tima = self.tma - count - print "raising" self.interrupt.raise_interrupt(constants.TIMER) print self.interrupt.timer.is_pending(), self.interrupt.is_pending(constants.TIMER) Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/video.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/video.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/video.py Fri May 9 11:16:20 2008 @@ -8,39 +8,38 @@ class Video(object): #frames = 0 - #frameSkip = 0 + #frame_skip = 0 # Line Buffer, constants.OAM Cache and Color Palette #line = []#= new int[8 + 160 + 8] #objects = []#= new int[OBJECTS_PER_LINE] #palette = []#= new int[1024] - def __init__(self, videoDriver, interrupt, memory): - self.driver = videoDriver + def __init__(self, video_driver, interrupt, memory): + self.driver = video_driver self.interrupt = interrupt self.memory = memory self.reset() def get_frame_skip(self): - return self.frameSkip + return self.frame_skip - def set_frame_skip(self, frameSkip): - self.frameSkip = frameSkip + def set_frame_skip(self, frame_skip): + self.frame_skip = frame_skip def reset(self): self.cycles = constants.MODE_2_TICKS - self.control = 0x91 self.stat = 2 - self.lineY = 0 - self.lineYCompare = 0 + self.line_y = 0 + self.line_y_compare = 0 self.dma = 0xFF - self.scrollY = 0 - self.scrollX = 0 - self.windowY = self.wlineY = 0 - self.windowX = 0 - self.backgroundPalette = 0xFC - self.objectPalette0 = self.objectPalette1 = 0xFF + self.scroll_y = 0 + self.scroll_x = 0 + self.window_y = self.wline_y = 0 + self.window_x = 0 + self.background_palette = 0xFC + self.object_palette_0 = self.object_palette_1 = 0xFF self.transfer = True self.display = True @@ -55,7 +54,7 @@ self.palette = [0] * 1024 self.frames = 0 - self.frameSkip = 0 + self.frame_skip = 0 def write(self, address, data): # assert data >= 0x00 and data <= 0xFF @@ -68,7 +67,7 @@ elif address == constants.SCX: self.set_scroll_x(data) elif address == constants.LY: - # Read OnlineY + # Read Online_y pass elif address == constants.LYC: self.set_ly_compare(data) @@ -159,8 +158,8 @@ self.reset_control(data) # don't draw window if it was not enabled and not being drawn before if (self.control & 0x20) == 0 and (data & 0x20) != 0 and \ - self.wlineY == 0 and self.lineY > self.windowY: - self.wlineY = 144 + self.wline_y == 0 and self.line_y > self.window_y: + self.wline_y = 144 self.control = data def reset_control(self, data): @@ -168,12 +167,12 @@ if (data & 0x80) != 0: self.stat = (self.stat & 0xFC) | 0x02 self.cycles = constants.MODE_2_TICKS - self.lineY = 0 + self.line_y = 0 self.display = False else: self.stat = (self.stat & 0xFC) | 0x00 self.cycles = constants.MODE_1_TICKS - self.lineY = 0 + self.line_y = 0 self.clear_frame() def get_status(self): @@ -187,28 +186,28 @@ self.interrupt.raise_interrupt(constants.LCD) def get_scroll_y(self): - return self.scrollY + return self.scroll_y def set_scroll_y(self, data): - self.scrollY = data + self.scroll_y = data def get_scroll_x(self): - return self.scrollX + return self.scroll_x def set_scroll_x(self, data): - self.scrollX = data + self.scroll_x = data def get_line_y(self): - return self.lineY + return self.line_y def get_line_y_compare(self): - return self.lineYCompare + return self.line_y_compare def set_ly_compare(self, data): - self.lineYCompare = data + self.line_y_compare = data if (self.control & 0x80) == 0: return - if self.lineY == self.lineYCompare: + if self.line_y == self.line_y_compare: # NOTE: raise interrupt once per line if (self.stat & 0x04) == 0: # constants.LYC=LY interrupt @@ -227,40 +226,40 @@ self.oam[index] = self.memory.read((self.dma << 8) + index) def get_background_palette(self): - return self.backgroundPalette + return self.background_palette def set_background_palette(self, data): - if self.backgroundPalette != data: - self.backgroundPalette = data + if self.background_palette != data: + self.background_palette = data self.dirty = True def get_object_palette_0(self): - return self.objectPalette0 + return self.object_palette_0 def set_object_palette_0(self, data): - if self.objectPalette0 != data: - self.objectPalette0 = data + if self.object_palette_0 != data: + self.object_palette_0 = data self.dirty = True def get_object_palette_1(self): - return self.objectPalette1 + return self.object_palette_1 def set_object_palette_1(self, data): - if self.objectPalette1 != data: - self.objectPalette1 = data + if self.object_palette_1 != data: + self.object_palette_1 = data self.dirty = True def get_window_y(self): - return self.windowY + return self.window_y def set_window_y(self, data): - self.windowY = data + self.window_y = data def get_window_x(self): - return self.windowX + return self.window_x def set_window_x(self, data): - self.windowX = data + self.window_x = data def emulate_oam(self): self.stat = (self.stat & 0xFC) | 0x03 @@ -282,15 +281,15 @@ self.interrupt.raise_interrupt(constants.LCD) def emulate_hblank(self): - self.lineY+=1 + self.line_y+=1 self.emulate_hblank_line_y_compare() - if self.lineY < 144: + if self.line_y < 144: self.emulate_hblank_part_1() else: self.emulate_hblank_part_2() def emulate_hblank_line_y_compare(self): - if self.lineY == self.lineYCompare: + if self.line_y == self.line_y_compare: # constants.LYC=LY interrupt self.stat |= 0x04 if (self.stat & 0x40) != 0: @@ -309,7 +308,7 @@ if self.display: self.drawFrame() self.frames += 1 - if self.frames >= self.frameSkip: + if self.frames >= self.frame_skip: self.display = True self.frames = 0 else: @@ -322,7 +321,7 @@ def emulate_vblank(self): if self.vblank: self.emulate_vblank_vblank() - elif self.lineY == 0: + elif self.line_y == 0: self.emulate_vblank_first_y_line() else: self.emulate_vblank_other() @@ -345,18 +344,18 @@ self.interrupt.raise_interrupt(constants.LCD) def emulate_vblank_other(self): - if self.lineY < 153: - self.lineY+=1 + if self.line_y < 153: + self.line_y+=1 self.stat = (self.stat & 0xFC) | 0x01 - if self.lineY == 153: + if self.line_y == 153: self.cycles += constants.MODE_1_END_TICKS else: self.cycles += constants.MODE_1_TICKS else: - self.lineY = self.wlineY = 0 + self.line_y = self.wline_y = 0 self.stat = (self.stat & 0xFC) | 0x01 self.cycles += constants.MODE_1_TICKS - constants.MODE_1_END_TICKS - if self.lineY == self.lineYCompare: + if self.line_y == self.line_y_compare: # constants.LYC=LY interrupt self.stat |= 0x04 if (self.stat & 0x40) != 0: @@ -387,8 +386,8 @@ self.line[x] = 0x00 def draw_background(self): - y = (self.scrollY + self.lineY) & 0xFF - x = self.scrollX & 0xFF + y = (self.scroll_y + self.line_y) & 0xFF + x = self.scroll_x & 0xFF tileMap = constants.VRAM_MAP_A if (self.control & 0x08) != 0: tileMap = constants.VRAM_MAP_B @@ -400,8 +399,8 @@ self.draw_tiles(8 - (x & 7), tileMap, tileData) def draw_window(self): - if self.lineY < self.windowY or self.windowX >= 167 or \ - self.wlineY >= 144: + if self.line_y < self.window_y or self.window_x >= 167 or \ + self.wline_y >= 144: return tileMap = constants.VRAM_MAP_A if (self.control & 0x40) != 0: @@ -409,10 +408,10 @@ tileData = constants.VRAM_DATA_B if (self.control & 0x10) != 0: tileData = constants.VRAM_DATA_A - tileMap += (self.wlineY >> 3) << 5 - tileData += (self.wlineY & 7) << 1 - self.draw_tiles(self.windowX + 1, tileMap, tileData) - self.wlineY+=1 + tileMap += (self.wline_y >> 3) << 5 + tileData += (self.wline_y & 7) << 1 + self.draw_tiles(self.window_x + 1, tileMap, tileData) + self.wline_y+=1 def draw_objects(self): count = self.scan_objects() @@ -439,7 +438,7 @@ tile = self.oam[offset + 2] & 0xFF flags = self.oam[offset + 3] & 0xFF - y = self.lineY - y + 16 + y = self.line_y - y + 16 if ((self.control & 0x04) != 0): # 8x16 tile size @@ -545,7 +544,7 @@ def draw_pixels(self): self.update_palette() pixels = self.driver.get_pixels() - offset = self.lineY * self.driver.get_width() + offset = self.line_y * self.driver.get_width() for x in range(8, 168, 4): for i in range(0,4): pattern = self.line[x + i] @@ -567,14 +566,14 @@ if (pattern & 0x22) == 0 or ((pattern & 0x08) != 0 and \ (pattern & 0x11) != 0): # constants.OBJ behind constants.BG color 1-3 - color = (self.backgroundPalette >> ((((pattern >> 3) & 0x02) +\ + color = (self.background_palette >> ((((pattern >> 3) & 0x02) +\ (pattern & 0x01)) << 1)) & 0x03 # constants.OBJ above constants.BG elif ((pattern & 0x04) == 0): - color = (self.objectPalette0 >> ((((pattern >> 4) & 0x02) + \ + color = (self.object_palette_0 >> ((((pattern >> 4) & 0x02) + \ ((pattern >> 1) & 0x01)) << 1)) & 0x03 else: - color = (self.objectPalette1 >> ((((pattern >> 4) & 0x02) +\ + color = (self.object_palette_1 >> ((((pattern >> 4) & 0x02) +\ ((pattern >> 1) & 0x01)) << 1)) & 0x03 index= ((pattern & 0x30) << 4) + (pattern & 0x0F) self.palette[index] = constants.COLOR_MAP[color] From arigo at codespeak.net Fri May 9 11:38:03 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 9 May 2008 11:38:03 +0200 (CEST) Subject: [pypy-svn] r54580 - in pypy/branch/gc-tweak/pypy/rpython: lltypesystem memory memory/test Message-ID: <20080509093803.5B5A8169DB4@codespeak.net> Author: arigo Date: Fri May 9 11:38:01 2008 New Revision: 54580 Added: pypy/branch/gc-tweak/pypy/rpython/memory/lldict.py (contents, props changed) pypy/branch/gc-tweak/pypy/rpython/memory/test/test_lldict.py (contents, props changed) Modified: pypy/branch/gc-tweak/pypy/rpython/lltypesystem/rdict.py pypy/branch/gc-tweak/pypy/rpython/memory/support.py pypy/branch/gc-tweak/pypy/rpython/memory/test/test_support.py Log: Kill this address tree and replace it with code that reuses pypy.rpython.lltypesystem.rdict. Looks much saner now (not to mention efficient). The new lldict.py depends strongly on the internal details of rdict.py, but at least, if we change rdict.py, test_lldict should cleanly fail. Modified: pypy/branch/gc-tweak/pypy/rpython/lltypesystem/rdict.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/lltypesystem/rdict.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/lltypesystem/rdict.py Fri May 9 11:38:01 2008 @@ -76,6 +76,8 @@ # compute the shape of the DICTENTRY structure entryfields = [] entrymeths = { + 'allocate': lltype.typeMethod(_ll_malloc_entries), + 'delete': _ll_free_entries, 'must_clear_key': (isinstance(self.DICTKEY, lltype.Ptr) and self.DICTKEY._needsgc()), 'must_clear_value': (isinstance(self.DICTVALUE, lltype.Ptr) @@ -189,6 +191,7 @@ } adtmeths['KEY'] = self.DICTKEY adtmeths['VALUE'] = self.DICTVALUE + adtmeths['allocate'] = lltype.typeMethod(_ll_malloc_dict) self.DICT.become(lltype.GcStruct("dicttable", adtmeths=adtmeths, *fields)) @@ -485,7 +488,7 @@ new_size = old_size * 2 while new_size > DICT_INITSIZE and d.num_items < new_size / 4: new_size /= 2 - d.entries = lltype.malloc(lltype.typeOf(old_entries).TO, new_size, zero=True) + d.entries = lltype.typeOf(old_entries).TO.allocate(new_size) d.num_items = 0 d.num_pristine_entries = new_size i = 0 @@ -495,6 +498,7 @@ entry = old_entries[i] ll_dict_insertclean(d, entry.key, entry.value, hash) i += 1 + old_entries.delete() # ------- a port of CPython's dictobject.c's lookdict implementation ------- PERTURB_SHIFT = 5 @@ -582,8 +586,8 @@ DICT_INITSIZE = 8 def ll_newdict(DICT): - d = lltype.malloc(DICT) - d.entries = lltype.malloc(DICT.entries.TO, DICT_INITSIZE, zero=True) + d = DICT.allocate() + d.entries = DICT.entries.TO.allocate(DICT_INITSIZE) d.num_items = 0 d.num_pristine_entries = DICT_INITSIZE return d @@ -594,13 +598,23 @@ n = DICT_INITSIZE while n < length_estimate: n *= 2 - d = lltype.malloc(DICT) - d.entries = lltype.malloc(DICT.entries.TO, n, zero=True) + d = DICT.allocate() + d.entries = DICT.entries.TO.allocate(n) d.num_items = 0 d.num_pristine_entries = DICT_INITSIZE return d ll_newdict_size.oopspec = 'newdict()' +# pypy.rpython.memory.lldict uses a dict based on Struct and Array +# instead of GcStruct and GcArray, which is done by using different +# 'allocate' and 'delete' adtmethod implementations than the ones below +def _ll_malloc_dict(DICT): + return lltype.malloc(DICT) +def _ll_malloc_entries(ENTRIES, n): + return lltype.malloc(ENTRIES, n, zero=True) +def _ll_free_entries(entries): + pass + def rtype_r_dict(hop): r_dict = hop.r_result @@ -691,8 +705,8 @@ def ll_copy(dict): DICT = lltype.typeOf(dict).TO dictsize = len(dict.entries) - d = lltype.malloc(DICT) - d.entries = lltype.malloc(DICT.entries.TO, dictsize, zero=True) + d = DICT.allocate() + d.entries = DICT.entries.TO.allocate(dictsize) d.num_items = dict.num_items d.num_pristine_entries = dict.num_pristine_entries if hasattr(DICT, 'fnkeyeq'): d.fnkeyeq = dict.fnkeyeq @@ -713,10 +727,11 @@ def ll_clear(d): if len(d.entries) == d.num_pristine_entries == DICT_INITSIZE: return - DICT = lltype.typeOf(d).TO - d.entries = lltype.malloc(DICT.entries.TO, DICT_INITSIZE, zero=True) + old_entries = d.entries + d.entries = lltype.typeOf(old_entries).TO.allocate(DICT_INITSIZE) d.num_items = 0 d.num_pristine_entries = DICT_INITSIZE + old_entries.delete() def ll_update(dic1, dic2): entries = dic2.entries Added: pypy/branch/gc-tweak/pypy/rpython/memory/lldict.py ============================================================================== --- (empty file) +++ pypy/branch/gc-tweak/pypy/rpython/memory/lldict.py Fri May 9 11:38:01 2008 @@ -0,0 +1,82 @@ +from pypy.rpython.lltypesystem import lltype, llmemory +from pypy.rpython.lltypesystem import rdict +from pypy.rlib.objectmodel import we_are_translated + +# This is a low-level AddressDict, reusing a lot of the logic from rdict.py. +# xxx this is very dependent on the details of rdict.py + +alloc_count = 0 # for debugging + +def count_alloc(delta): + "NOT_RPYTHON" + global alloc_count + alloc_count += delta + + +def newdict(): + return rdict.ll_newdict(DICT) + +def dict_allocate(): + if not we_are_translated(): count_alloc(+1) + return lltype.malloc(DICT, flavor="raw") + +def dict_delete(d): + dict_delete_entries(d.entries) + lltype.free(d, flavor="raw") + if not we_are_translated(): count_alloc(-1) + +def dict_allocate_entries(n): + if not we_are_translated(): count_alloc(+1) + # 'raw zero varsize malloc with length field' is not really implemented. + # we can initialize the memory to zero manually + entries = lltype.malloc(ENTRIES, n, flavor="raw") + i = 0 + while i < n: + entries[i].key = llmemory.NULL + i += 1 + return entries + +def dict_delete_entries(entries): + lltype.free(entries, flavor="raw") + if not we_are_translated(): count_alloc(-1) + +_hash = llmemory.cast_adr_to_int + +def dict_keyhash(d, key): + return _hash(key) + +def dict_entry_valid(entries, i): + return entries[i].key != llmemory.NULL + +def dict_entry_hash(entries, i): + return _hash(entries[i].key) + +def dict_get(d, key, default=llmemory.NULL): + return rdict.ll_get(d, key, default) + +def dict_add(d, key): + rdict.ll_dict_setitem(d, key, llmemory.NULL) + +ENTRY = lltype.Struct('ENTRY', ('key', llmemory.Address), + ('value', llmemory.Address)) +ENTRIES = lltype.Array(ENTRY, + adtmeths = { + 'allocate': dict_allocate_entries, + 'delete': dict_delete_entries, + 'valid': dict_entry_valid, + 'everused': dict_entry_valid, + 'hash': dict_entry_hash, + }) +DICT = lltype.Struct('DICT', ('entries', lltype.Ptr(ENTRIES)), + ('num_items', lltype.Signed), + ('num_pristine_entries', lltype.Signed), + adtmeths = { + 'allocate': dict_allocate, + 'delete': dict_delete, + 'contains': rdict.ll_contains, + 'setitem': rdict.ll_dict_setitem, + 'get': dict_get, + 'add': dict_add, + 'keyhash': dict_keyhash, + 'keyeq': None, + }) Modified: pypy/branch/gc-tweak/pypy/rpython/memory/support.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/memory/support.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/memory/support.py Fri May 9 11:38:01 2008 @@ -127,12 +127,15 @@ def stack2dict(self): result = AddressDict() - self.foreach(result.setitem, llmemory.NULL) + self.foreach(_add_in_dict, result) return result cache[chunk_size] = AddressStack return AddressStack +def _add_in_dict(item, d): + d.add(item) + def get_address_deque(chunk_size=DEFAULT_CHUNK_SIZE, cache={}): try: @@ -200,10 +203,12 @@ cache[chunk_size] = AddressDeque return AddressDeque +# ____________________________________________________________ def AddressDict(): if we_are_translated(): - return LLAddressDict() + from pypy.rpython.memory import lldict + return lldict.newdict() else: return BasicAddressDict() @@ -223,128 +228,3 @@ self.data[self._key(keyaddr)] = valueaddr def add(self, keyaddr): self.setitem(keyaddr, llmemory.NULL) - -# if diff_bit == -1, the node is a key/value pair (key=left/value=right) -# if diff_bit >= 0, then the node is the root of a subtree where: -# * the keys have all exactly the same bits > diff_bit -# * the keys whose 'diff_bit' is 0 are in the 'left' subtree -# * the keys whose 'diff_bit' is 1 are in the 'right' subtree -ADDRDICTNODE = lltype.Struct('AddrDictNode', - ('diff_bit', lltype.Signed), - ('left', llmemory.Address), - ('right', llmemory.Address)) - -class LLAddressDict(object): - _alloc_flavor_ = "raw" - - def __init__(self): - self.root = lltype.malloc(ADDRDICTNODE, flavor='raw') - self.root.diff_bit = -1 - self.root.left = llmemory.NULL - - def delete(self): - node = self.root - parent = lltype.nullptr(ADDRDICTNODE) - while True: - if node.diff_bit >= 0: - next = _node_reveal(node.left) - node.left = _node_hide(parent) - parent = node - node = next - else: - lltype.free(node, flavor='raw') - if not parent: - break - node = _node_reveal(parent.right) - grandparent = _node_reveal(parent.left) - lltype.free(parent, flavor='raw') - parent = grandparent - free_non_gc_object(self) - - def contains(self, keyaddr): - if keyaddr: - node = self._lookup(keyaddr) - return keyaddr == node.left - else: - return False - - def get(self, keyaddr, default=llmemory.NULL): - if keyaddr: - node = self._lookup(keyaddr) - if keyaddr == node.left: - return node.right - return default - - def setitem(self, keyaddr, valueaddr): - ll_assert(bool(keyaddr), "cannot store NULL in an AddressDict") - node = self._lookup(keyaddr) - if node.left == llmemory.NULL or node.left == keyaddr: - node.left = keyaddr - node.right = valueaddr - else: - number1 = r_uint(llmemory.cast_adr_to_int(keyaddr)) - number2 = r_uint(llmemory.cast_adr_to_int(node.left)) - diff = number1 ^ number2 - parentnode = self._lookup(keyaddr, difflimit = diff >> 1) - # all subnodes of parentnode have a key that is equal to - # 'keyaddr' for all bits in range(0, msb(diff)), and differs - # from 'keyaddr' exactly at bit msb(diff). - # At this point, parentnode.diff_bit < msb(diff). - nextbit = parentnode.diff_bit - copynode = lltype.malloc(ADDRDICTNODE, flavor='raw') - copynode.diff_bit = nextbit - copynode.left = parentnode.left - copynode.right = parentnode.right - bit = self._msb(diff, nextbit + 1) - newnode = lltype.malloc(ADDRDICTNODE, flavor='raw') - parentnode.diff_bit = bit - ll_assert(number1 & (r_uint(1) << bit) != - number2 & (r_uint(1) << bit), "setitem: bad 'bit'") - if number1 & (r_uint(1) << bit): - parentnode.left = _node_hide(copynode) - parentnode.right = _node_hide(newnode) - else: - parentnode.left = _node_hide(newnode) - parentnode.right = _node_hide(copynode) - newnode.diff_bit = -1 - newnode.left = keyaddr - newnode.right = valueaddr - if not we_are_translated(): - assert self.contains(keyaddr) - - def add(self, keyaddr): - self.setitem(keyaddr, llmemory.NULL) - - def _msb(self, value, lowerbound=0): - # Most Significant Bit: '(1<= (r_uint(1) << lowerbound), - "msb: bad value or lowerbound") - if value >= (r_uint(1) << (LONG_BIT-1)): - return LONG_BIT-1 # most significant possible bit - bit = lowerbound - while (value >> bit) > r_uint(1): - bit += 1 - return bit - - def _lookup(self, addr, difflimit=r_uint(0)): - # * with difflimit == 0, find and return the leaf node whose key is - # equal to or closest from 'addr'. - # * with difflimit > 0, look for the node N closest to the root such - # that all the keys of the subtree starting at node N are equal to - # the given 'addr' at least for all bits > msb(difflimit). - number = r_uint(llmemory.cast_adr_to_int(addr)) - node = self.root - while node.diff_bit >= 0: - mask = r_uint(1) << node.diff_bit - if mask <= difflimit: - return node - if number & mask: - node = _node_reveal(node.right) - else: - node = _node_reveal(node.left) - return node - -_node_hide = llmemory.cast_ptr_to_adr - -def _node_reveal(nodeaddr): - return llmemory.cast_adr_to_ptr(nodeaddr, lltype.Ptr(ADDRDICTNODE)) Added: pypy/branch/gc-tweak/pypy/rpython/memory/test/test_lldict.py ============================================================================== --- (empty file) +++ pypy/branch/gc-tweak/pypy/rpython/memory/test/test_lldict.py Fri May 9 11:38:01 2008 @@ -0,0 +1,64 @@ +import random, sys +from pypy.rpython.lltypesystem import lltype, llmemory +from pypy.rpython.memory import lldict + + +class TestLLAddressDict: + + def setup_method(self, meth): + lldict.alloc_count = 0 + + def test_basics(self): + d = lldict.newdict() + d.add(intaddr(42)) + d.setitem(intaddr(43), intaddr(44)) + assert not d.contains(intaddr(41)) + assert d.contains(intaddr(42)) + assert d.contains(intaddr(43)) + assert not d.contains(intaddr(44)) + assert d.get(intaddr(41)) == llmemory.NULL + assert d.get(intaddr(42)) == llmemory.NULL + assert d.get(intaddr(43)) == intaddr(44) + assert d.get(intaddr(44)) == llmemory.NULL + d.delete() + assert lldict.alloc_count == 0 + + def test_random(self): + for i in range(8) + range(8, 80, 10): + examples = {} + lst = [] + for j in range(i): + if j % 17 == 13: + intval = random.choice(lst) + else: + intval = random.randrange(-sys.maxint, sys.maxint) or 1 + lst.append(intval) + examples[intval] = True + + d = lldict.newdict() + for intval in lst: + d.setitem(intaddr(intval), intaddr(-intval)) + for intval in lst: + assert d.contains(intaddr(intval)) + assert d.get(intaddr(intval), "???").intval == -intval + for intval in lst: + for j in range(intval-5, intval+5): + if j not in examples: + assert not d.contains(intaddr(j)) + assert not d.contains(llmemory.NULL) + d.delete() + assert lldict.alloc_count == 0 + + +class intaddr(object): + _TYPE = llmemory.Address + def __init__(self, intval): + self.intval = intval + def _cast_to_int(self): + return self.intval + def __repr__(self): + return '' % (self.intval & (sys.maxint*2+1),) + def __eq__(self, other): + return isinstance(other, intaddr) and self.intval == other.intval + def __ne__(self, other): + return not self.__eq__(other) Modified: pypy/branch/gc-tweak/pypy/rpython/memory/test/test_support.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/memory/test/test_support.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/memory/test/test_support.py Fri May 9 11:38:01 2008 @@ -1,8 +1,6 @@ -import sys from pypy.rlib.objectmodel import free_non_gc_object from pypy.rpython.memory.support import get_address_stack from pypy.rpython.memory.support import get_address_deque -from pypy.rpython.memory.support import LLAddressDict from pypy.rpython.test.test_llinterp import interpret from pypy.rpython.lltypesystem import lltype, llmemory @@ -141,44 +139,3 @@ AddressStack = get_address_stack() res = interpret(f, [], malloc_check=False) assert res - - -def test_LLAddressDict(): - import random - - class intaddr(object): - _TYPE = llmemory.Address - def __init__(self, intval): - self.intval = intval - def _cast_to_int(self): - return self.intval - def __repr__(self): - return '' % (self.intval & (sys.maxint*2+1),) - def __eq__(self, other): - return isinstance(other, intaddr) and self.intval == other.intval - def __ne__(self, other): - return not self.__eq__(other) - - for i in range(8) + range(8, 80, 10): - examples = {} - lst = [] - for j in range(i): - if j % 17 == 13: - intval = random.choice(lst) - else: - intval = random.randrange(-sys.maxint, sys.maxint) or 1 - lst.append(intval) - examples[intval] = True - - d = LLAddressDict() - for intval in lst: - d.setitem(intaddr(intval), intaddr(-intval)) - for intval in lst: - assert d.contains(intaddr(intval)) - assert d.get(intaddr(intval), "???").intval == -intval - for intval in lst: - for j in range(intval-5, intval+5): - if j not in examples: - assert not d.contains(intaddr(j)) - assert not d.contains(llmemory.NULL) - d.delete() From arigo at codespeak.net Fri May 9 11:56:44 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 9 May 2008 11:56:44 +0200 (CEST) Subject: [pypy-svn] r54581 - pypy/dist/pypy/rpython/lltypesystem Message-ID: <20080509095644.E7FA5169ED7@codespeak.net> Author: arigo Date: Fri May 9 11:56:44 2008 New Revision: 54581 Modified: pypy/dist/pypy/rpython/lltypesystem/rdict.py Log: Oups! Performance bug. (This function is not used after translation so far, so it wasn't so bad.) Modified: pypy/dist/pypy/rpython/lltypesystem/rdict.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rdict.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rdict.py Fri May 9 11:56:44 2008 @@ -597,7 +597,7 @@ d = lltype.malloc(DICT) d.entries = lltype.malloc(DICT.entries.TO, n, zero=True) d.num_items = 0 - d.num_pristine_entries = DICT_INITSIZE + d.num_pristine_entries = n return d ll_newdict_size.oopspec = 'newdict()' From arigo at codespeak.net Fri May 9 12:10:12 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 9 May 2008 12:10:12 +0200 (CEST) Subject: [pypy-svn] r54582 - in pypy/branch/gc-tweak/pypy/rpython: lltypesystem memory memory/test Message-ID: <20080509101012.1797A169F8A@codespeak.net> Author: arigo Date: Fri May 9 12:10:11 2008 New Revision: 54582 Modified: pypy/branch/gc-tweak/pypy/rpython/lltypesystem/rdict.py pypy/branch/gc-tweak/pypy/rpython/memory/lldict.py pypy/branch/gc-tweak/pypy/rpython/memory/support.py pypy/branch/gc-tweak/pypy/rpython/memory/test/test_lldict.py Log: A copy_and_update() helper. Modified: pypy/branch/gc-tweak/pypy/rpython/lltypesystem/rdict.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/lltypesystem/rdict.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/lltypesystem/rdict.py Fri May 9 12:10:11 2008 @@ -601,7 +601,7 @@ d = DICT.allocate() d.entries = DICT.entries.TO.allocate(n) d.num_items = 0 - d.num_pristine_entries = DICT_INITSIZE + d.num_pristine_entries = n return d ll_newdict_size.oopspec = 'newdict()' Modified: pypy/branch/gc-tweak/pypy/rpython/memory/lldict.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/memory/lldict.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/memory/lldict.py Fri May 9 12:10:11 2008 @@ -13,8 +13,8 @@ alloc_count += delta -def newdict(): - return rdict.ll_newdict(DICT) +def newdict(length_estimate=0): + return rdict.ll_newdict_size(DICT, length_estimate) def dict_allocate(): if not we_are_translated(): count_alloc(+1) @@ -57,6 +57,15 @@ def dict_add(d, key): rdict.ll_dict_setitem(d, key, llmemory.NULL) +def dict_foreach(d, callback, arg): + entries = d.entries + i = len(entries) - 1 + while i >= 0: + if dict_entry_valid(entries, i): + callback(entries[i].key, entries[i].value, arg) + i -= 1 +dict_foreach._annspecialcase_ = 'specialize:arg(1)' + ENTRY = lltype.Struct('ENTRY', ('key', llmemory.Address), ('value', llmemory.Address)) ENTRIES = lltype.Array(ENTRY, @@ -73,10 +82,12 @@ adtmeths = { 'allocate': dict_allocate, 'delete': dict_delete, + 'length': rdict.ll_dict_len, 'contains': rdict.ll_contains, 'setitem': rdict.ll_dict_setitem, 'get': dict_get, 'add': dict_add, + 'foreach': dict_foreach, 'keyhash': dict_keyhash, 'keyeq': None, }) Modified: pypy/branch/gc-tweak/pypy/rpython/memory/support.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/memory/support.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/memory/support.py Fri May 9 12:10:11 2008 @@ -111,6 +111,14 @@ cur = next free_non_gc_object(self) + def length(self): + chunk = self.chunk + count = self.used_in_last_chunk + while chunk: + chunk = chunk.next + count += chunk_size + return count + def foreach(self, callback, arg): """Invoke 'callback(address, arg)' for all addresses in the stack. Typically, 'callback' is a bound method and 'arg' can be None. @@ -126,7 +134,7 @@ foreach._annspecialcase_ = 'specialize:arg(1)' def stack2dict(self): - result = AddressDict() + result = AddressDict(self.length()) self.foreach(_add_in_dict, result) return result @@ -205,26 +213,66 @@ # ____________________________________________________________ -def AddressDict(): +def AddressDict(length_estimate=0): if we_are_translated(): from pypy.rpython.memory import lldict - return lldict.newdict() + return lldict.newdict(length_estimate) else: return BasicAddressDict() class BasicAddressDict(object): + def __init__(self): self.data = {} + def _key(self, addr): return addr._fixup().ptr._obj + def delete(self): pass + + def length(self): + return len(self.data) + def contains(self, keyaddr): return self._key(keyaddr) in self.data + def get(self, keyaddr, default=llmemory.NULL): return self.data.get(self._key(keyaddr), default) + def setitem(self, keyaddr, valueaddr): assert keyaddr self.data[self._key(keyaddr)] = valueaddr + def add(self, keyaddr): self.setitem(keyaddr, llmemory.NULL) + + def foreach(self, callback, arg): + """Invoke 'callback(key, value, arg)' for all items in the dict. + Typically, 'callback' is a bound method and 'arg' can be None.""" + for key, value in self.data.iteritems(): + callback(key, value, arg) + + +def copy_and_update(dict, surviving, updated_address): + """Make a copy of 'dict' in which the keys are updated as follows: + * if surviving(key) returns False, the item is removed + * otherwise, updated_address(key) is inserted in the copy. + """ + newdict = AddressDict + if not we_are_translated(): + # when not translated, return a dict of the same kind as 'dict' + if not isinstance(dict, BasicAddressDict): + from pypy.rpython.memory.lldict import newdict + result = newdict(dict.length()) + dict.foreach(_get_updater(surviving, updated_address), result) + return result +copy_and_update._annspecialcase_ = 'specialize:arg(1,2)' + +def _get_updater(surviving, updated_address): + def callback(key, value, arg): + if surviving(key): + newkey = updated_address(key) + arg.setitem(newkey, value) + return callback +_get_updater._annspecialcase_ = 'specialize:memo' Modified: pypy/branch/gc-tweak/pypy/rpython/memory/test/test_lldict.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/memory/test/test_lldict.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/memory/test/test_lldict.py Fri May 9 12:10:11 2008 @@ -1,6 +1,6 @@ import random, sys from pypy.rpython.lltypesystem import lltype, llmemory -from pypy.rpython.memory import lldict +from pypy.rpython.memory import support, lldict class TestLLAddressDict: @@ -20,9 +20,46 @@ assert d.get(intaddr(42)) == llmemory.NULL assert d.get(intaddr(43)) == intaddr(44) assert d.get(intaddr(44)) == llmemory.NULL + assert d.length() == 2 d.delete() assert lldict.alloc_count == 0 + def test_foreach(self): + d = lldict.newdict() + for i in range(30): + d.setitem(intaddr(0x100 * i), intaddr(i)) + result = [] + d.foreach(lambda key, value, arg: result.append((key, value, arg)), + "hello world") + assert len(result) == 30 + seen = {} + for key, value, arg in result: + assert key.intval == 0x100 * value.intval + assert arg == "hello world" + seen[key.intval] = True + assert len(seen) == 30 + d.delete() + assert lldict.alloc_count == 0 + + def test_copy_and_update(self): + d = lldict.newdict() + d.setitem(intaddr(41), intaddr(44)) + d.setitem(intaddr(42), intaddr(45)) + d.setitem(intaddr(43), intaddr(46)) + def surviving(key): + return key.intval != 41 + def updated_address(key): + return intaddr({42: 42, 43: 99}[key.intval]) + d2 = support.copy_and_update(d, surviving, updated_address) + d.delete() + assert d2.length() == 2 + assert d2.get(intaddr(41)) == llmemory.NULL + assert d2.get(intaddr(42)) == intaddr(45) + assert d2.get(intaddr(43)) == llmemory.NULL + assert d2.get(intaddr(99)) == intaddr(46) + d2.delete() + assert lldict.alloc_count == 0 + def test_random(self): for i in range(8) + range(8, 80, 10): examples = {} From fijal at codespeak.net Fri May 9 12:36:07 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 9 May 2008 12:36:07 +0200 (CEST) Subject: [pypy-svn] r54583 - pypy/branch/io-improvements/pypy Message-ID: <20080509103607.3FAEF16A1D5@codespeak.net> Author: fijal Date: Fri May 9 12:36:05 2008 New Revision: 54583 Modified: pypy/branch/io-improvements/pypy/FAILURES Log: update, not to forget Modified: pypy/branch/io-improvements/pypy/FAILURES ============================================================================== --- pypy/branch/io-improvements/pypy/FAILURES (original) +++ pypy/branch/io-improvements/pypy/FAILURES Fri May 9 12:36:05 2008 @@ -1,2 +1,2 @@ -rpython/test/test_rbuiltin.py +rpython/memory/test/test_tranformed_gc.py -k test_llinterp_tuple From fijal at codespeak.net Fri May 9 12:42:45 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 9 May 2008 12:42:45 +0200 (CEST) Subject: [pypy-svn] r54584 - in pypy/branch/io-improvements/pypy/rpython/memory: gctransform test Message-ID: <20080509104245.CC1FE16A20D@codespeak.net> Author: fijal Date: Fri May 9 12:42:43 2008 New Revision: 54584 Modified: pypy/branch/io-improvements/pypy/rpython/memory/gctransform/transform.py pypy/branch/io-improvements/pypy/rpython/memory/test/test_transformed_gc.py Log: A test and a fix Modified: pypy/branch/io-improvements/pypy/rpython/memory/gctransform/transform.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/memory/gctransform/transform.py (original) +++ pypy/branch/io-improvements/pypy/rpython/memory/gctransform/transform.py Fri May 9 12:42:43 2008 @@ -574,10 +574,9 @@ # fish resvar v_newbuf = hop.llops[-1].result v_src = op.args[0] + v_lgt = op.args[1] TYPE = v_src.concretetype.TO c_fldname = rmodel.inputconst(lltype.Void, TYPE._arrayfld) - v_lgt = hop.genop('getinteriorarraysize', [v_src, c_fldname], - resulttype=lltype.Signed) v_adrsrc = hop.genop('cast_ptr_to_adr', [v_src], resulttype=llmemory.Address) v_adrnewbuf = hop.genop('cast_ptr_to_adr', [v_newbuf], @@ -600,7 +599,8 @@ op = hop.spaceop if self._can_realloc(): return self._gct_resize_buffer_realloc(hop) - return hop.genop('same_as', [op.args[0]], resultvar=op.result) + else: + return self._gct_resize_buffer_no_realloc(hop) def varsize_malloc_helper(self, hop, flags, meth, extraargs): def intconst(c): return rmodel.inputconst(lltype.Signed, c) Modified: pypy/branch/io-improvements/pypy/rpython/memory/test/test_transformed_gc.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/memory/test/test_transformed_gc.py (original) +++ pypy/branch/io-improvements/pypy/rpython/memory/test/test_transformed_gc.py Fri May 9 12:42:43 2008 @@ -500,7 +500,7 @@ def f(): ptr = rgc.resizable_buffer_of_shape(STR, 2) ptr.chars[0] = 'a' - ptr = rgc.resize_buffer(ptr, 1, 2) + ptr = rgc.resize_buffer(ptr, 1, 200) ptr.chars[1] = 'b' return len(hlstr(rgc.finish_building_buffer(ptr, 2))) From fijal at codespeak.net Fri May 9 12:43:38 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 9 May 2008 12:43:38 +0200 (CEST) Subject: [pypy-svn] r54585 - pypy/branch/io-improvements/pypy/translator/c/test Message-ID: <20080509104338.697DA16A20D@codespeak.net> Author: fijal Date: Fri May 9 12:43:37 2008 New Revision: 54585 Modified: pypy/branch/io-improvements/pypy/translator/c/test/test_boehm.py Log: just to be sure, overallocate here as well. Modified: pypy/branch/io-improvements/pypy/translator/c/test/test_boehm.py ============================================================================== --- pypy/branch/io-improvements/pypy/translator/c/test/test_boehm.py (original) +++ pypy/branch/io-improvements/pypy/translator/c/test/test_boehm.py Fri May 9 12:43:37 2008 @@ -385,7 +385,7 @@ def f(): ptr = rgc.resizable_buffer_of_shape(STR, 2) ptr.chars[0] = 'a' - ptr = rgc.resize_buffer(ptr, 1, 2) + ptr = rgc.resize_buffer(ptr, 1, 200) ptr.chars[1] = 'b' return hlstr(rgc.finish_building_buffer(ptr, 2)) == "ab" From arigo at codespeak.net Fri May 9 13:35:30 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 9 May 2008 13:35:30 +0200 (CEST) Subject: [pypy-svn] r54586 - pypy/branch/gc-tweak/pypy/rpython/lltypesystem Message-ID: <20080509113530.06A7039B679@codespeak.net> Author: arigo Date: Fri May 9 13:35:30 2008 New Revision: 54586 Modified: pypy/branch/gc-tweak/pypy/rpython/lltypesystem/llmemory.py pypy/branch/gc-tweak/pypy/rpython/lltypesystem/lltype.py Log: Implement cast_int_to_adr() for direct running too. Modified: pypy/branch/gc-tweak/pypy/rpython/lltypesystem/llmemory.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/lltypesystem/llmemory.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/lltypesystem/llmemory.py Fri May 9 13:35:30 2008 @@ -582,8 +582,10 @@ def cast_adr_to_int(adr): return adr._cast_to_int() +_NONGCREF = lltype.Ptr(lltype.OpaqueType('NONGCREF')) def cast_int_to_adr(int): - raise NotImplementedError("cast_int_to_adr") + ptr = lltype.cast_int_to_ptr(_NONGCREF, int) + return cast_ptr_to_adr(ptr) # ____________________________________________________________ # Weakrefs. Modified: pypy/branch/gc-tweak/pypy/rpython/lltypesystem/lltype.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/lltypesystem/lltype.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/lltypesystem/lltype.py Fri May 9 13:35:30 2008 @@ -905,6 +905,8 @@ return p # primitive if not p: return None # null pointer + if type(p._obj0) is int: + return p # a pointer obtained by cast_int_to_ptr container = p._obj._normalizedcontainer() if container is not p._obj: p = _ptr(Ptr(typeOf(container)), container, p._solid) @@ -985,7 +987,7 @@ _obj = property(_getobj) def _was_freed(self): - return (self._obj0 is not None and + return (type(self._obj0) not in (type(None), int) and self._getobj(check=False)._was_freed()) def __getattr__(self, field_name): # ! can only return basic or ptr ! From arigo at codespeak.net Fri May 9 13:37:21 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 9 May 2008 13:37:21 +0200 (CEST) Subject: [pypy-svn] r54587 - in pypy/branch/gc-tweak/pypy/rpython/memory: . gc gc/test test Message-ID: <20080509113721.B552639B679@codespeak.net> Author: arigo Date: Fri May 9 13:37:18 2008 New Revision: 54587 Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gc/base.py pypy/branch/gc-tweak/pypy/rpython/memory/gc/generation.py pypy/branch/gc-tweak/pypy/rpython/memory/gc/hybrid.py pypy/branch/gc-tweak/pypy/rpython/memory/gc/semispace.py pypy/branch/gc-tweak/pypy/rpython/memory/gc/test/test_direct.py pypy/branch/gc-tweak/pypy/rpython/memory/lldict.py pypy/branch/gc-tweak/pypy/rpython/memory/support.py pypy/branch/gc-tweak/pypy/rpython/memory/test/test_lldict.py Log: (likely inprogress) Kill kill kill the obscure id() logic, and replace it with something custom but sane in each GC class. Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gc/base.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/memory/gc/base.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/memory/gc/base.py Fri May 9 13:37:18 2008 @@ -198,110 +198,6 @@ class MovingGCBase(GCBase): moving_gc = True - def __init__(self): - # WaRnInG! Putting GC objects as fields of the GC itself is - # basically *not* working in general! When running tests with - # the gcwrapper, there is no way they can be returned from - # get_roots_from_llinterp(). When the whole GC goes through the - # gctransformer, though, it works if the fields are read-only - # (and thus only ever reference a prebuilt list or dict). These - # prebuilt lists or dicts themselves can be mutated and point to - # more non-prebuild GC objects; this is fine because the - # internal GC ptr in the prebuilt list or dict is found by - # gctypelayout and listed in addresses_of_static_ptrs. - - # XXX I'm not sure any more about the warning above. The fields - # of 'self' are found by gctypelayout and added to - # addresses_of_static_ptrs_in_nongc, so in principle they could - # be mutated and still be found by collect(). - - self.wr_to_objects_with_id = [] - self.object_id_dict = {} - self.object_id_dict_ends_at = 0 - - def id(self, ptr): - self.disable_finalizers() - try: - return self._compute_id(ptr) - finally: - self.enable_finalizers() - - def _compute_id(self, ptr): - # XXX this may explode if --no-translation-rweakref is specified - # ---------------------------------------------------------------- - # Basic logic: the list item wr_to_objects_with_id[i] contains a - # weakref to the object whose id is i + 1. The object_id_dict is - # an optimization that tries to reduce the number of linear - # searches in this list. - # ---------------------------------------------------------------- - # Invariant: if object_id_dict_ends_at >= 0, then object_id_dict - # contains all pairs {address: id}, for the addresses - # of all objects that are the targets of the weakrefs of the - # following slice: wr_to_objects_with_id[:object_id_dict_ends_at]. - # ---------------------------------------------------------------- - # Essential: as long as notify_objects_just_moved() is not called, - # we assume that the objects' addresses did not change. We also - # assume that the address of a live object cannot be reused for - # another object without an intervening notify_objects_just_moved() - # call, but this could be fixed easily if needed. - # ---------------------------------------------------------------- - # First check the dictionary - i = self.object_id_dict_ends_at - if i < 0: - self.object_id_dict.clear() # dictionary invalid - self.object_id_dict_ends_at = 0 - i = 0 - else: - adr = llmemory.cast_ptr_to_adr(ptr) - try: - i = self.object_id_dict[adr] - except KeyError: - pass - else: - # double-check that the answer we got is correct - lst = self.wr_to_objects_with_id - target = llmemory.weakref_deref(llmemory.GCREF, lst[i]) - ll_assert(target == ptr, "bogus object_id_dict") - return i + 1 # found via the dict - # Walk the tail of the list, where entries are not also in the dict - lst = self.wr_to_objects_with_id - end = len(lst) - freeentry = -1 - while i < end: - target = llmemory.weakref_deref(llmemory.GCREF, lst[i]) - if not target: - freeentry = i - else: - ll_assert(self.get_type_id(llmemory.cast_ptr_to_adr(target)) - > 0, "bogus weakref in compute_id()") - # record this entry in the dict - adr = llmemory.cast_ptr_to_adr(target) - self.object_id_dict[adr] = i - if target == ptr: - break # found - i += 1 - else: - # not found - wr = llmemory.weakref_create(ptr) - if freeentry < 0: - ll_assert(end == len(lst), "unexpected lst growth in gc_id") - i = end - lst.append(wr) - else: - i = freeentry # reuse the id() of a dead object - lst[i] = wr - adr = llmemory.cast_ptr_to_adr(ptr) - self.object_id_dict[adr] = i - # all entries up to and including index 'i' are now valid in the dict - # unless a collection occurred while we were working, in which case - # the object_id_dict is bogus anyway - if self.object_id_dict_ends_at >= 0: - self.object_id_dict_ends_at = i + 1 - return i + 1 # this produces id() values 1, 2, 3, 4... - - def notify_objects_just_moved(self): - self.object_id_dict_ends_at = -1 - def choose_gc_from_config(config): """Return a (GCClass, GC_PARAMS) from the given config object. Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gc/generation.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/memory/gc/generation.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/memory/gc/generation.py Fri May 9 13:37:18 2008 @@ -62,6 +62,7 @@ # it lists exactly the old and static objects whose # GCFLAG_NO_YOUNG_PTRS bit is not set. self.young_objects_with_weakrefs = self.AddressStack() + self.young_objects_with_id = self.AddressDict() self.reset_nursery() # compute the constant lower bounds for the attributes @@ -249,6 +250,7 @@ def semispace_collect(self, size_changing=False): self.reset_young_gcflags() # we are doing a full collection anyway self.weakrefs_grow_older() + self.ids_grow_older() self.reset_nursery() if DEBUG_PRINT: llop.debug_print(lltype.Void, "major collect, size changing", size_changing) @@ -343,7 +345,8 @@ # GCFLAG_NO_YOUNG_PTRS set again by trace_and_drag_out_of_nursery if self.young_objects_with_weakrefs.non_empty(): self.invalidate_young_weakrefs() - self.notify_objects_just_moved() + if self.young_objects_with_id.length() > 0: + self.update_young_objects_with_id() # mark the nursery as free and fill it with zeroes again llarena.arena_reset(self.nursery, self.nursery_size, True) if DEBUG_PRINT: @@ -454,6 +457,28 @@ # overridden by HybridGC return (self.header(obj).tid & GCFLAG_EXTERNAL) != 0 + def _compute_id(self, obj): + if self.is_in_nursery(obj): + result = self.young_objects_with_id.get(obj) + if not result: + result = self._next_id() + self.young_objects_with_id.setitem(obj, result) + return result + else: + return SemiSpaceGC._compute_id(self, obj) + + def update_young_objects_with_id(self): + self.young_objects_with_id.foreach(self._update_object_id, + self.objects_with_id) + self.young_objects_with_id.clear() + + def ids_grow_older(self): + self.young_objects_with_id.foreach(self._id_grow_older, None) + self.young_objects_with_id.clear() + + def _id_grow_older(self, obj, id, ignored): + self.objects_with_id.setitem(obj, id) + def debug_check_object(self, obj): """Check the invariants about 'obj' that should be true between collections.""" Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gc/hybrid.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/memory/gc/hybrid.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/memory/gc/hybrid.py Fri May 9 13:37:18 2008 @@ -466,6 +466,22 @@ dead_size, "bytes in", dead_count, "objs") + def _compute_id_for_external(self, obj): + # the base classes make the assumption that all external objects + # have an id equal to their address. This is wrong if the object + # is a generation 3 rawmalloced object that initially lived in + # the semispaces. + if self.is_last_generation(obj): + # in this case, we still need to check if the object had its + # id taken before. If not, we can use its address as its id. + return self.objects_with_id.get(obj, obj) + else: + # a generation 2 external object was never non-external in + # the past, so it cannot be listed in self.objects_with_id. + return obj + # XXX a possible optimization would be to use three dicts, one + # for each generation, instead of mixing gen2 and gen3 objects. + def debug_check_object(self, obj): """Check the invariants about 'obj' that should be true between collections.""" Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gc/semispace.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/memory/gc/semispace.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/memory/gc/semispace.py Fri May 9 13:37:18 2008 @@ -3,6 +3,7 @@ from pypy.rpython.lltypesystem.llmemory import NULL, raw_malloc_usage from pypy.rpython.memory.support import DEFAULT_CHUNK_SIZE from pypy.rpython.memory.support import get_address_stack, get_address_deque +from pypy.rpython.memory.support import AddressDict from pypy.rpython.memory.gcheader import GCHeaderBuilder from pypy.rpython.lltypesystem import lltype, llmemory, llarena from pypy.rlib.objectmodel import free_non_gc_object @@ -50,8 +51,11 @@ self.gcheaderbuilder = GCHeaderBuilder(self.HDR) self.AddressStack = get_address_stack(chunk_size) self.AddressDeque = get_address_deque(chunk_size) + self.AddressDict = AddressDict self.finalizer_lock_count = 0 self.red_zone = 0 + self.id_free_list = self.AddressStack() + self.next_free_id = 1 def setup(self): if DEBUG_PRINT: @@ -66,6 +70,7 @@ self.objects_with_finalizers = self.AddressDeque() self.run_finalizers = self.AddressDeque() self.objects_with_weakrefs = self.AddressStack() + self.objects_with_id = self.AddressDict() def disable_finalizers(self): self.finalizer_lock_count += 1 @@ -235,9 +240,9 @@ scan = self.deal_with_objects_with_finalizers(scan) if self.objects_with_weakrefs.non_empty(): self.invalidate_weakrefs() + self.update_objects_with_id() self.finished_full_collect() self.debug_check_consistency() - self.notify_objects_just_moved() if not size_changing: llarena.arena_reset(fromspace, self.space_size, True) self.record_red_zone() @@ -573,6 +578,62 @@ finally: self.finalizer_lock_count -= 1 + def id(self, ptr): + obj = llmemory.cast_ptr_to_adr(ptr) + if self.header(obj).tid & GCFLAG_EXTERNAL: + result = self._compute_id_for_external(obj) + else: + result = self._compute_id(obj) + return llmemory.cast_adr_to_int(result) + + def _next_id(self): + # return an id not currently in use (as an address instead of an int) + if self.id_free_list.non_empty(): + result = self.id_free_list.pop() # reuse a dead id + else: + # make up a fresh id number + result = llmemory.cast_int_to_adr(self.next_free_id) + self.next_free_id += 2 # only odd numbers, to make lltype + # and llmemory happy and to avoid + # clashes with real addresses + return result + + def _compute_id(self, obj): + # look if the object is listed in objects_with_id + result = self.objects_with_id.get(obj) + if not result: + result = self._next_id() + self.objects_with_id.setitem(obj, result) + return result + + def _compute_id_for_external(self, obj): + # For prebuilt objects, we can simply return their address. + # This method is overriden by the HybridGC. + return obj + + def update_objects_with_id(self): + old = self.objects_with_id + new_objects_with_id = self.AddressDict(old.length()) + old.foreach(self._update_object_id_FAST, new_objects_with_id) + old.delete() + self.objects_with_id = new_objects_with_id + + def _update_object_id(self, obj, id, new_objects_with_id): + # safe version (used by subclasses) + if self.surviving(obj): + newobj = self.get_forwarding_address(obj) + new_objects_with_id.setitem(newobj, id) + else: + self.id_free_list.append(id) + + def _update_object_id_FAST(self, obj, id, new_objects_with_id): + # unsafe version, assumes that the new_objects_with_id is large enough + if self.surviving(obj): + newobj = self.get_forwarding_address(obj) + new_objects_with_id.insertclean(newobj, id) + else: + self.id_free_list.append(id) + def debug_check_object(self, obj): """Check the invariants about 'obj' that should be true between collections.""" Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gc/test/test_direct.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/memory/gc/test/test_direct.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/memory/gc/test/test_direct.py Fri May 9 13:37:18 2008 @@ -238,6 +238,32 @@ self.gc.collect() verify() + def test_id(self): + ids = {} + def allocate_bunch(count=50): + base = len(self.stackroots) + for i in range(count): + p = self.malloc(S) + self.stackroots.append(p) + for i in range(count): + j = base + (i*1291) % count + pid = self.gc.id(self.stackroots[j]) + assert isinstance(pid, int) + ids[j] = pid + def verify(): + for j, expected in ids.items(): + assert self.gc.id(self.stackroots[j]) == expected + allocate_bunch(5) + verify() + allocate_bunch(75) + verify() + allocate_bunch(5) + verify() + self.gc.collect() + verify() + self.gc.collect() + verify() + class TestSemiSpaceGC(DirectGCTest): from pypy.rpython.memory.gc.semispace import SemiSpaceGC as GCClass Modified: pypy/branch/gc-tweak/pypy/rpython/memory/lldict.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/memory/lldict.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/memory/lldict.py Fri May 9 13:37:18 2008 @@ -57,6 +57,9 @@ def dict_add(d, key): rdict.ll_dict_setitem(d, key, llmemory.NULL) +def dict_insertclean(d, key, value): + rdict.ll_dict_insertclean(d, key, value, _hash(key)) + def dict_foreach(d, callback, arg): entries = d.entries i = len(entries) - 1 @@ -87,6 +90,8 @@ 'setitem': rdict.ll_dict_setitem, 'get': dict_get, 'add': dict_add, + 'insertclean': dict_insertclean, + 'clear': rdict.ll_clear, 'foreach': dict_foreach, 'keyhash': dict_keyhash, 'keyeq': None, Modified: pypy/branch/gc-tweak/pypy/rpython/memory/support.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/memory/support.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/memory/support.py Fri May 9 13:37:18 2008 @@ -228,6 +228,9 @@ def _key(self, addr): return addr._fixup().ptr._obj + def _wrapkey(self, obj): + return llmemory.cast_ptr_to_adr(obj._as_ptr()) + def delete(self): pass @@ -244,14 +247,23 @@ assert keyaddr self.data[self._key(keyaddr)] = valueaddr + def insertclean(self, keyaddr, valueaddr): + assert keyaddr + key = self._key(keyaddr) + assert key not in self.data + self.data[key] = valueaddr + def add(self, keyaddr): self.setitem(keyaddr, llmemory.NULL) + def clear(self): + self.data.clear() + def foreach(self, callback, arg): """Invoke 'callback(key, value, arg)' for all items in the dict. Typically, 'callback' is a bound method and 'arg' can be None.""" for key, value in self.data.iteritems(): - callback(key, value, arg) + callback(self._wrapkey(key), value, arg) def copy_and_update(dict, surviving, updated_address): Modified: pypy/branch/gc-tweak/pypy/rpython/memory/test/test_lldict.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/memory/test/test_lldict.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/memory/test/test_lldict.py Fri May 9 13:37:18 2008 @@ -42,9 +42,9 @@ assert lldict.alloc_count == 0 def test_copy_and_update(self): - d = lldict.newdict() + d = lldict.newdict(3) d.setitem(intaddr(41), intaddr(44)) - d.setitem(intaddr(42), intaddr(45)) + d.insertclean(intaddr(42), intaddr(45)) d.setitem(intaddr(43), intaddr(46)) def surviving(key): return key.intval != 41 @@ -60,6 +60,15 @@ d2.delete() assert lldict.alloc_count == 0 + def test_clear(self): + d = lldict.newdict() + d.setitem(intaddr(41), intaddr(42)) + d.clear() + assert d.length() == 0 + assert not d.contains(intaddr(41)) + d.delete() + assert lldict.alloc_count == 0 + def test_random(self): for i in range(8) + range(8, 80, 10): examples = {} From arigo at codespeak.net Fri May 9 13:42:35 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 9 May 2008 13:42:35 +0200 (CEST) Subject: [pypy-svn] r54588 - in pypy/branch/gc-tweak/pypy/rpython/memory: . gc Message-ID: <20080509114235.EF21639B679@codespeak.net> Author: arigo Date: Fri May 9 13:42:33 2008 New Revision: 54588 Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gc/generation.py pypy/branch/gc-tweak/pypy/rpython/memory/support.py Log: Translation fixes. All id tests seem to pass. Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gc/generation.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/memory/gc/generation.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/memory/gc/generation.py Fri May 9 13:42:33 2008 @@ -62,7 +62,6 @@ # it lists exactly the old and static objects whose # GCFLAG_NO_YOUNG_PTRS bit is not set. self.young_objects_with_weakrefs = self.AddressStack() - self.young_objects_with_id = self.AddressDict() self.reset_nursery() # compute the constant lower bounds for the attributes @@ -76,6 +75,7 @@ def setup(self): self.last_generation_root_objects = self.AddressStack() + self.young_objects_with_id = self.AddressDict() SemiSpaceGC.setup(self) self.set_nursery_size(self.initial_nursery_size) # the GC is fully setup now. The rest can make use of it. Modified: pypy/branch/gc-tweak/pypy/rpython/memory/support.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/memory/support.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/memory/support.py Fri May 9 13:42:33 2008 @@ -226,6 +226,7 @@ self.data = {} def _key(self, addr): + "NOT_RPYTHON: prebuilt AddressDicts are not supported" return addr._fixup().ptr._obj def _wrapkey(self, obj): From arigo at codespeak.net Fri May 9 14:01:05 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 9 May 2008 14:01:05 +0200 (CEST) Subject: [pypy-svn] r54589 - in pypy/branch/gc-tweak/pypy/rpython/memory: . gc test Message-ID: <20080509120105.2108E39B67D@codespeak.net> Author: arigo Date: Fri May 9 14:01:04 2008 New Revision: 54589 Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gc/generation.py pypy/branch/gc-tweak/pypy/rpython/memory/lldict.py pypy/branch/gc-tweak/pypy/rpython/memory/support.py pypy/branch/gc-tweak/pypy/rpython/memory/test/test_lldict.py Log: A further small tweak. Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gc/generation.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/memory/gc/generation.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/memory/gc/generation.py Fri May 9 14:01:04 2008 @@ -468,13 +468,16 @@ return SemiSpaceGC._compute_id(self, obj) def update_young_objects_with_id(self): - self.young_objects_with_id.foreach(self._update_object_id, - self.objects_with_id) - self.young_objects_with_id.clear() + # 'foreach_clear' iterates over the items in the dict and clears + # it in the same pass. It does not shrink the dictionary, which + # is appropriate for our use case: the dict will tend to be large + # enough for the maximum number of objects with id that exist in + # the nursery, and stay at that size for the rest of the execution. + self.young_objects_with_id.foreach_clear(self._update_object_id, + self.objects_with_id) def ids_grow_older(self): - self.young_objects_with_id.foreach(self._id_grow_older, None) - self.young_objects_with_id.clear() + self.young_objects_with_id.foreach_clear(self._id_grow_older, None) def _id_grow_older(self, obj, id, ignored): self.objects_with_id.setitem(obj, id) Modified: pypy/branch/gc-tweak/pypy/rpython/memory/lldict.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/memory/lldict.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/memory/lldict.py Fri May 9 14:01:04 2008 @@ -69,6 +69,19 @@ i -= 1 dict_foreach._annspecialcase_ = 'specialize:arg(1)' +def dict_foreach_clear(d, callback, arg): + entries = d.entries + i = len(entries) - 1 + while i >= 0: + if dict_entry_valid(entries, i): + key = entries[i].key + entries[i].key = llmemory.NULL + callback(key, entries[i].value, arg) + i -= 1 + d.num_items = 0 + d.num_pristine_entries = len(entries) +dict_foreach_clear._annspecialcase_ = 'specialize:arg(1)' + ENTRY = lltype.Struct('ENTRY', ('key', llmemory.Address), ('value', llmemory.Address)) ENTRIES = lltype.Array(ENTRY, @@ -91,8 +104,8 @@ 'get': dict_get, 'add': dict_add, 'insertclean': dict_insertclean, - 'clear': rdict.ll_clear, 'foreach': dict_foreach, + 'foreach_clear': dict_foreach_clear, 'keyhash': dict_keyhash, 'keyeq': None, }) Modified: pypy/branch/gc-tweak/pypy/rpython/memory/support.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/memory/support.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/memory/support.py Fri May 9 14:01:04 2008 @@ -257,7 +257,8 @@ def add(self, keyaddr): self.setitem(keyaddr, llmemory.NULL) - def clear(self): + def foreach_clear(self, callback, arg): + self.foreach(callback, arg) self.data.clear() def foreach(self, callback, arg): Modified: pypy/branch/gc-tweak/pypy/rpython/memory/test/test_lldict.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/memory/test/test_lldict.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/memory/test/test_lldict.py Fri May 9 14:01:04 2008 @@ -60,12 +60,18 @@ d2.delete() assert lldict.alloc_count == 0 - def test_clear(self): + def test_foreach_clear(self): d = lldict.newdict() d.setitem(intaddr(41), intaddr(42)) - d.clear() + result = [] + d.foreach_clear(lambda key, value, arg: result.append((key,value,arg)), + "hello world") assert d.length() == 0 assert not d.contains(intaddr(41)) + assert len(result) == 1 + assert result[0][0].intval == 41 + assert result[0][1].intval == 42 + assert result[0][2] == "hello world" d.delete() assert lldict.alloc_count == 0 From arigo at codespeak.net Fri May 9 14:58:21 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 9 May 2008 14:58:21 +0200 (CEST) Subject: [pypy-svn] r54590 - pypy/dist/pypy/lib Message-ID: <20080509125821.B0DB539B688@codespeak.net> Author: arigo Date: Fri May 9 14:58:21 2008 New Revision: 54590 Modified: pypy/dist/pypy/lib/_locale.py Log: This name may be undefined. Modified: pypy/dist/pypy/lib/_locale.py ============================================================================== --- pypy/dist/pypy/lib/_locale.py (original) +++ pypy/dist/pypy/lib/_locale.py Fri May 9 14:58:21 2008 @@ -414,8 +414,10 @@ 'Error', 'setlocale', 'localeconv', 'strxfrm', 'strcoll', 'gettext', 'dgettext', 'dcgettext', 'textdomain', - 'bindtextdomain', 'bind_textdomain_codeset', + 'bindtextdomain', ) +if _bind_textdomain_codeset: + __all__ += ('bind_textdomain_codeset',) if HAS_LANGINFO: __all__ += ('nl_langinfo',) From cfbolz at codespeak.net Fri May 9 14:58:30 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 9 May 2008 14:58:30 +0200 (CEST) Subject: [pypy-svn] r54591 - pypy/extradoc/talk/s3-2008 Message-ID: <20080509125830.3410D39B68C@codespeak.net> Author: cfbolz Date: Fri May 9 14:58:29 2008 New Revision: 54591 Modified: pypy/extradoc/talk/s3-2008/talk.tex Log: the slides about pypy in the s3 talk Modified: pypy/extradoc/talk/s3-2008/talk.tex ============================================================================== --- pypy/extradoc/talk/s3-2008/talk.tex (original) +++ pypy/extradoc/talk/s3-2008/talk.tex Fri May 9 14:58:29 2008 @@ -52,22 +52,77 @@ % You might wish to add the option [pausesections] %\end{frame} -\begin{frame} - \frametitle{Scope} - This talk is about: XXX - \begin{itemize} - \item - writing a Squeak implementation - \item - with eight people - \item - in five days - \item - using PyPy -\end{frame} - - - +\frame{ + \frametitle{Scope} + This talk is about: XXX + \itemize{ + \item writing a Squeak implementation + \item with eight people + \item in five days + \item using PyPy + } +} + + +\frame{ + \frametitle{What is PyPy} + \itemize{ + \item started as a Python implementation in Python + \item developed into a general environment for implementing dynamic languages + \item supports the language developer with a lot of infrastructure + \item Open Source project, MIT license + \item most important goal: abstracting over low-level details + \item don't fix decisions about low-level details + } +} + +\frame{ + \frametitle{PyPy's Approach to VM Construction} + \itemize{ + \item implement an interpreter for the dynamic language in RPython + \item translate this interpreter to a low-level language + \item translating inserts low-level details + \item a variety of target environment: C, LLVM, JVM, .NET + % XXX write about model-driven development? + } + \pause + \begin{block} {What is RPython?} + \itemize{ + \item a more static subset of Python + \item static enough to enable type inference + \item still rather expressive: exceptions, inheritance, dynamic dispatch + \item analysis starts after importing of interpreter + \item enables compile-time metaprogramming + } + \end{block} +} + +\frame{ + \begin{block} {Translation Aspects} + \itemize{ + \item many aspects of the final VM are orthogonal to language semantics + \item examples: GC strategy, threading model, many object details + \item non-trivial translation aspect: auto-generating a dynamic compiler + \item those shouldn't manifest in the interpreter source + \item they are inserted during translation + } + \end{block} + \pause + \begin{block} {Compile-Time Metaprogramming} + \itemize{ + \item PyPy's translation toolchain starts analysis after importing + \item arbitrary (non-RPython) code can be executed during import + \item this allows metaprogramming of parts of the interpreter + } + \end{block} +} + +\frame{ + \frametitle{The SPy VM} + \itemize{ + \item foo + } +} \end{document} From cami at codespeak.net Fri May 9 15:17:55 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Fri, 9 May 2008 15:17:55 +0200 (CEST) Subject: [pypy-svn] r54592 - in pypy/branch/gameboy-emulator/pypy/lang/gameboy: . test Message-ID: <20080509131755.9238039B679@codespeak.net> Author: cami Date: Fri May 9 15:17:53 2008 New Revision: 54592 Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboyImplementation.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/joypad.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/ram.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cpu.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_register.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/timer.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/video.py Log: added assertion for better annotation Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py Fri May 9 15:17:53 2008 @@ -2,6 +2,8 @@ # ___________________________________________________________________________ from pypy.lang.gameboy import constants +from pypy.lang.gameboy.timer import * + import os def has_cartridge_battery(self, cartridge_type): @@ -31,8 +33,9 @@ class CartridgeManager(object): - def __init__(self, clock_driver): - self.clock = clock_driver + def __init__(self, clock): + assert isinstance(clock, Clock) + self.clock = clock self.cartridge = None def reset(self): Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py Fri May 9 15:17:53 2008 @@ -1,9 +1,12 @@ -from pypy.lang.gameboy import constants +from pypy.lang.gameboy import constants +from pypy.lang.gameboy.ram import * +from pypy.lang.gameboy.interrupt import * class Register(object): def __init__(self, cpu, value=0): + assert isinstance(cpu, CPU) self.reset_value = self.value = value self.cpu = cpu if value != 0: @@ -30,16 +33,11 @@ class DoubleRegister(object): - def __init__(self, cpu, hi=None, lo=None, reset_value=0): + def __init__(self, cpu, hi, lo, reset_value=0): + assert isinstance(cpu, CPU) self.cpu = cpu - if hi == None : - self.hi = Register(self.cpu) - else: - self.hi = hi - if lo == None: - self.lo = Register(self.cpu) - else: - self.lo = lo + self.hi = hi + self.lo = lo self.reset_value = reset_value def set(self, hi=0, lo=None, use_cycles=True): @@ -90,6 +88,7 @@ class ImmediatePseudoRegister(object): def __init__(self, cpu, hl): + assert isinstance(cpu, CPU) self.cpu = cpu self.hl = hl @@ -108,6 +107,7 @@ class FlagRegister(object): def __init__(self, cpu): + assert isinstance(cpu, CPU) self.cpu = cpu self.reset() @@ -174,6 +174,7 @@ Central Unit ProcessOR (Sharp LR35902 CPU) """ def __init__(self, interrupt, memory): + assert isinstance(interrupt, Interrupt) self.interrupt = interrupt self.memory = memory self.ime = False @@ -197,8 +198,8 @@ self.hl = DoubleRegister(self, self.h, self.l, constants.RESET_HL) self.hli = ImmediatePseudoRegister(self, self.hl) - self.pc = DoubleRegister(self, reset_value=constants.RESET_PC) - self.sp = DoubleRegister(self, reset_value=constants.RESET_SP) + self.pc = DoubleRegister(self, Register(self), Register(self), reset_value=constants.RESET_PC) + self.sp = DoubleRegister(self, Register(self), Register(self), reset_value=constants.RESET_SP) self.a = Register(self, constants.RESET_A) self.f = FlagRegister(self) @@ -344,7 +345,7 @@ def read(self, hi, lo=None): # memory Access, 1 cycle address = hi - if lo != None: + if lo is not None: address = (hi << 8) + lo self.cycles -= 1 return self.memory.read(address) @@ -391,7 +392,7 @@ def pop_double_register(self, getter, register=None): # 3 cycles - if register == None: + if register is None: register = getter getter = CPU.pop b = getter(self) # 1 cycle @@ -887,7 +888,7 @@ return opCodes def group_lambda(function, registerGetter, value=None): - if value == None: + if value is None: return lambda s: function(s, registerGetter(s).get, registerGetter(s).set) else: return lambda s: function(s, registerGetter(s).get, registerGetter(s).set, value) Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboyImplementation.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboyImplementation.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboyImplementation.py Fri May 9 15:17:53 2008 @@ -1,11 +1,14 @@ +#!/usr/bin/env python import pyglet pyglet.options['audio'] = ('openal', 'silent') from pyglet import window -from pyglet.window import key from pyglet import media +from pyglet import image +from pyglet.window import key +from pypy.lang.gameboy.gameboy import * from pypy.lang.gameboy.joypad import JoypadDriver from pypy.lang.gameboy.video import VideoDriver from pypy.lang.gameboy.sound import SoundDriver @@ -18,6 +21,7 @@ def __init__(self): self.create_window() GameBoy.__init__(self) + self.mainLoop() def create_window(self): self.win = window.Window() @@ -27,28 +31,57 @@ self.clock = Clock() self.joypad_driver = JoypadDriverImplementation(self.win) self.video_driver = VideoDriverImplementation(self.win) - self.sound_driver = SoundDriverImplementation(self.win) + self.sound_driver = SoundDriverImplementation() + def mainLoop(self): + while not self.win.has_exit: + pass + +# VIDEO DRIVER ----------------------------------------------------------------- +class VideoDriverImplementation(VideoDriver): + + def __init__(self, win): + VideoDriver.__init__(self) + self.win = win + self.win.on_resize = self.on_resize + self.set_window_size() + self.create_image_buffer() + + def create_image_buffer(self): + self.buffers = image.get_buffer_manager() + self.image_buffer = self.buffers.get_color_buffer() + + def on_resize(self, width, height): + pass + + def set_window_size(self): + self.win.set_size(self.width, self.height) + + def update_display(self): + self.image_buffer.blit(0, 0) + self.win.flip() + + # JOYPAD DRIVER ---------------------------------------------------------------- -class JoypadDriverImplementation(object): +class JoypadDriverImplementation(JoypadDriver): - def __ini__(self, win): - JoypadDriver.__ini__(self) + def __init__(self, win): + JoypadDriver.__init__(self) self.create_button_key_codes() self.win = win self.create_listeners() def create_button_key_codes(self): - self.buttonKeyCodes = {key.UP : (self.buttonUp), - key.RIGHT : (self.buttonRight), - key.DOWN : (self.buttonDown), - key.LEFT : (self.buttonLeft), - key.ENTER : (self.buttonStart), - key.SPACE : (self.buttonSelect), - key.A : (self.buttonA), - key.B : (self.ButtonB)} + self.button_key_codes = {key.UP : (self.button_up), + key.RIGHT : (self.button_right), + key.DOWN : (self.button_down), + key.LEFT : (self.button_left), + key.ENTER : (self.button_start), + key.SPACE : (self.button_select), + key.A : (self.button_a), + key.B : (self.button_b)} def create_listeners(self): self.win.on_key_press = self.on_key_press @@ -65,10 +98,10 @@ pressButtonFunction(False) def get_button_handler(self, symbol, modifiers): - if symbol in self.buttonKeyCodes: - if len(self.buttonKeyCodes[symbol]) == 1 or\ - self.buttonKeyCodes[symbol][1] == modifiers: - return self.buttonKeyCodes[symbol][0] + if symbol in self.button_key_codes: + if len(self.button_key_codes[symbol]) == 1 or\ + self.button_key_codes[symbol][1] == modifiers: + return self.button_key_codes[symbol][0] return None @@ -97,34 +130,18 @@ pass -# VIDEO DRIVER ----------------------------------------------------------------- - -class VideoDriverImplementation(VideoDriver): - - def __init__(self, win): - VideoDriver.__init__(self) - self.win = win - self.win.on_resize = self.on_resize - self.set_window_size() - self.create_image_buffer() - - def create_image_buffer(self): - self.buffers = image.get_buffer_manager() - self.image_buffer = self.buffers.get_color_buffer() - - def on_resize(self, width, height): - pass - - def set_window_size(self): - self.win.setSize(self.width, self.height) - - def update_display(self): - self.image_buffer.blit(0, 0) - self.win.flip() - - # ============================================================================== if __name__ == '__main__': - print "starting gameboy" + entry_point() + + + +def entry_point(args): gameboy = GameBoyImplementation() + + +# _____ Define and setup target ___ + +def target(*args): + return entry_point, None Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/joypad.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/joypad.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/joypad.py Fri May 9 15:17:53 2008 @@ -166,7 +166,7 @@ class Button(object): def __init__(self, code_value, opposite_button=None): - self.code_value = code_value + self.code_value = int(code_value) self.opposite_button = opposite_button self.pressed = False Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/ram.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/ram.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/ram.py Fri May 9 15:17:53 2008 @@ -9,6 +9,10 @@ class RAM(object): def __init__(self): + # Work RAM + self.w_ram = [0x00]*8192 + # High RAM + self.h_ram = [0x00]*128 self.reset() def reset(self): Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py Fri May 9 15:17:53 2008 @@ -529,7 +529,7 @@ self.frequency_table[period] = skip def reset(self): - self.cycles = constants.GAMEBOY_CLOCK / constants.SOUND_CLOCK + self.cycles = int(constants.GAMEBOY_CLOCK / constants.SOUND_CLOCK) self.frames = 0 self.channel1.reset() self.channel2.reset() Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cpu.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cpu.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cpu.py Fri May 9 15:17:53 2008 @@ -176,7 +176,7 @@ assert len(entry) == 2 assert entry[0] == opCode assert entry[1].func_name == "" - assert entry[1].func_closure[0].cell_contents == func + #assert entry[1].func_closure[0].cell_contents == func opCode += step @@ -193,7 +193,7 @@ assert len(entry) == 2 assert entry[0] == opCode assert entry[1].func_name == "" - assert entry[1].func_closure[0].cell_contents == func + #assert entry[1].func_closure[0].cell_contents == func opCode += step # HELPERS Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_register.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_register.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_register.py Fri May 9 15:17:53 2008 @@ -63,7 +63,7 @@ def test_double_register_constructor(): cpu = get_cpu() - register = DoubleRegister(cpu) + register = DoubleRegister(cpu, Register(cpu), Register(cpu)) assert register.get() == 0 assert register.get_hi() == 0 assert register.get_lo() == 0 @@ -79,7 +79,8 @@ assert register.get_lo() == reg2.get() def test_double_register(): - register = DoubleRegister(get_cpu()) + cpu = get_cpu() + register = DoubleRegister(cpu, Register(cpu), Register(cpu)) value = 0x1234 oldCycles = register.cpu.cycles register.set(value) @@ -87,7 +88,8 @@ assert register.get() == value def test_double_register_bounds(): - register = DoubleRegister(get_cpu()) + cpu = get_cpu() + register = DoubleRegister(cpu, Register(cpu), Register(cpu)) value = 0xFFFF1234 register.set(value) assert register.get() == 0x1234 @@ -95,7 +97,8 @@ assert register.get() == 0 def test_double_register_hilo(): - register = DoubleRegister(get_cpu()) + cpu = get_cpu() + register = DoubleRegister(cpu, Register(cpu), Register(cpu)) value = 0x1234 valueHi = 0x12 valueLo = 0x34 @@ -123,7 +126,8 @@ def test_double_register_methods(): value = 0x1234 - register = DoubleRegister(get_cpu()) + cpu = get_cpu() + register = DoubleRegister(cpu, Register(cpu), Register(cpu)) register.set(value) oldCycles = register.cpu.cycles @@ -151,8 +155,8 @@ def test_double_register_reset(): value = 0x1234; - - register = DoubleRegister(get_cpu(), reset_value=value) + cpu = get_cpu() + register = DoubleRegister(cpu, Register(cpu), Register(cpu), reset_value=value) register.set(value+1) assert register.get() == value+1; register.reset() Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/timer.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/timer.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/timer.py Fri May 9 15:17:53 2008 @@ -5,11 +5,13 @@ """ from pypy.lang.gameboy import constants +from pypy.lang.gameboy.interrupt import * from math import ceil class Timer(object): def __init__(self, interrupt): + assert isinstance(interrupt, Interrupt) self.interrupt = interrupt self.reset() Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/video.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/video.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/video.py Fri May 9 15:17:53 2008 @@ -16,6 +16,7 @@ #palette = []#= new int[1024] def __init__(self, video_driver, interrupt, memory): + assert isinstance(video_driver, VideoDriver) self.driver = video_driver self.interrupt = interrupt self.memory = memory From cami at codespeak.net Fri May 9 15:26:54 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Fri, 9 May 2008 15:26:54 +0200 (CEST) Subject: [pypy-svn] r54593 - pypy/branch/gameboy-emulator/pypy/lang/gameboy Message-ID: <20080509132654.7210139B679@codespeak.net> Author: cami Date: Fri May 9 15:26:54 2008 New Revision: 54593 Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/serial.py Log: fixed some bugs, tested with more annotations Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py Fri May 9 15:26:54 2008 @@ -156,10 +156,10 @@ def load(self, cartridgeFilePath): - self.cartridgeFilePath = cartridgeFilePath - self.cartridgeName = os.path.basename(cartridgeFilePath) - self.cartridgeFile = open(cartridgeFilePath) - self._load_battery(cartridgeFilePath) + self.cartridgeFilePath = str(cartridgeFilePath) + self.cartridgeName = os.path.basename(self.cartridgeFilePath) + self.cartridgeFile = open(self.cartridgeFilePath) + self._load_battery(self.cartridgeFilePath) def _load_battery(self, cartridgeFilePath): Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/serial.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/serial.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/serial.py Fri May 9 15:26:54 2008 @@ -1,5 +1,6 @@ from pypy.lang.gameboy import constants +from pypy.lang.gameboy.interrupt import * class Serial(object): """ @@ -8,6 +9,7 @@ """ def __init__(self, interrupt): + assert isinstance(interrupt, Interrupt) self.interrupt = interrupt self.reset() From arigo at codespeak.net Fri May 9 15:50:30 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 9 May 2008 15:50:30 +0200 (CEST) Subject: [pypy-svn] r54594 - in pypy/branch/gc-tweak/pypy/rpython/memory: . gc test Message-ID: <20080509135030.55E4939B68F@codespeak.net> Author: arigo Date: Fri May 9 15:50:28 2008 New Revision: 54594 Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gc/generation.py pypy/branch/gc-tweak/pypy/rpython/memory/lldict.py pypy/branch/gc-tweak/pypy/rpython/memory/support.py pypy/branch/gc-tweak/pypy/rpython/memory/test/test_lldict.py Log: Revert r54589, which turned out to be a pessimization. Add comment about why (probably) it was a bad idea. Modified: pypy/branch/gc-tweak/pypy/rpython/memory/gc/generation.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/memory/gc/generation.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/memory/gc/generation.py Fri May 9 15:50:28 2008 @@ -468,16 +468,16 @@ return SemiSpaceGC._compute_id(self, obj) def update_young_objects_with_id(self): - # 'foreach_clear' iterates over the items in the dict and clears - # it in the same pass. It does not shrink the dictionary, which - # is appropriate for our use case: the dict will tend to be large - # enough for the maximum number of objects with id that exist in - # the nursery, and stay at that size for the rest of the execution. - self.young_objects_with_id.foreach_clear(self._update_object_id, - self.objects_with_id) + self.young_objects_with_id.foreach(self._update_object_id, + self.objects_with_id) + self.young_objects_with_id.clear() + # NB. the clear() also makes the dictionary shrink back to its + # minimal size, which is actually a good idea: a large, mostly-empty + # table is bad for the next call to 'foreach'. def ids_grow_older(self): - self.young_objects_with_id.foreach_clear(self._id_grow_older, None) + self.young_objects_with_id.foreach(self._id_grow_older, None) + self.young_objects_with_id.clear() def _id_grow_older(self, obj, id, ignored): self.objects_with_id.setitem(obj, id) Modified: pypy/branch/gc-tweak/pypy/rpython/memory/lldict.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/memory/lldict.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/memory/lldict.py Fri May 9 15:50:28 2008 @@ -69,19 +69,6 @@ i -= 1 dict_foreach._annspecialcase_ = 'specialize:arg(1)' -def dict_foreach_clear(d, callback, arg): - entries = d.entries - i = len(entries) - 1 - while i >= 0: - if dict_entry_valid(entries, i): - key = entries[i].key - entries[i].key = llmemory.NULL - callback(key, entries[i].value, arg) - i -= 1 - d.num_items = 0 - d.num_pristine_entries = len(entries) -dict_foreach_clear._annspecialcase_ = 'specialize:arg(1)' - ENTRY = lltype.Struct('ENTRY', ('key', llmemory.Address), ('value', llmemory.Address)) ENTRIES = lltype.Array(ENTRY, @@ -104,8 +91,8 @@ 'get': dict_get, 'add': dict_add, 'insertclean': dict_insertclean, + 'clear': rdict.ll_clear, 'foreach': dict_foreach, - 'foreach_clear': dict_foreach_clear, 'keyhash': dict_keyhash, 'keyeq': None, }) Modified: pypy/branch/gc-tweak/pypy/rpython/memory/support.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/memory/support.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/memory/support.py Fri May 9 15:50:28 2008 @@ -257,8 +257,7 @@ def add(self, keyaddr): self.setitem(keyaddr, llmemory.NULL) - def foreach_clear(self, callback, arg): - self.foreach(callback, arg) + def clear(self): self.data.clear() def foreach(self, callback, arg): Modified: pypy/branch/gc-tweak/pypy/rpython/memory/test/test_lldict.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/memory/test/test_lldict.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/memory/test/test_lldict.py Fri May 9 15:50:28 2008 @@ -60,18 +60,12 @@ d2.delete() assert lldict.alloc_count == 0 - def test_foreach_clear(self): + def test_clear(self): d = lldict.newdict() d.setitem(intaddr(41), intaddr(42)) - result = [] - d.foreach_clear(lambda key, value, arg: result.append((key,value,arg)), - "hello world") + d.clear() assert d.length() == 0 assert not d.contains(intaddr(41)) - assert len(result) == 1 - assert result[0][0].intval == 41 - assert result[0][1].intval == 42 - assert result[0][2] == "hello world" d.delete() assert lldict.alloc_count == 0 From tverwaes at codespeak.net Fri May 9 16:22:43 2008 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Fri, 9 May 2008 16:22:43 +0200 (CEST) Subject: [pypy-svn] r54596 - in pypy/branch/gameboy-emulator/pypy: lang/gameboy translator/goal Message-ID: <20080509142243.DDFA739B679@codespeak.net> Author: tverwaes Date: Fri May 9 16:22:43 2008 New Revision: 54596 Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py pypy/branch/gameboy-emulator/pypy/translator/goal/targetgbrom4.py Log: fixing some small bugs + make targetgbrom4 py.testable Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py Fri May 9 16:22:43 2008 @@ -157,7 +157,7 @@ def load(self, cartridgeFilePath): self.cartridgeFilePath = str(cartridgeFilePath) - self.cartridgeName = os.path.basename(self.cartridgeFilePath) + # self.cartridgeName = os.path.basename(self.cartridgeFilePath) self.cartridgeFile = open(self.cartridgeFilePath) self._load_battery(self.cartridgeFilePath) Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py Fri May 9 16:22:43 2008 @@ -35,6 +35,8 @@ def __init__(self, cpu, hi, lo, reset_value=0): assert isinstance(cpu, CPU) + assert isinstance(lo, Register) + assert isinstance(hi, Register) self.cpu = cpu self.hi = hi self.lo = lo @@ -104,7 +106,7 @@ # ------------------------------------------------------------------------------ -class FlagRegister(object): +class FlagRegister(Register): def __init__(self, cpu): assert isinstance(cpu, CPU) Modified: pypy/branch/gameboy-emulator/pypy/translator/goal/targetgbrom4.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/translator/goal/targetgbrom4.py (original) +++ pypy/branch/gameboy-emulator/pypy/translator/goal/targetgbrom4.py Fri May 9 16:22:43 2008 @@ -6,7 +6,7 @@ from pypy.lang.gameboy.gameboy import * -ROM_PATH = str(py.magic.autopath().dirpath().dirpath().dirpath())+"lang/gameboy/rom" +ROM_PATH = str(py.magic.autopath().dirpath().dirpath().dirpath())+"/lang/gameboy/rom" EMULATION_CYCLES = 64 @@ -23,12 +23,19 @@ def entry_point(argv): + #if len(argv) > 1: + # filename = argv[1] + #else: + # print "usage:", argv[0], "" + # return -1 gameBoy = GameBoy() - gameBoy.loadCartridgeFile(ROM_PATH+"/rom4/rom4.gb") + gameBoy.load_cartridge_file(ROM_PATH+"/rom4/rom4.gb")#filename) gameBoy.emulate(EMULATION_CYCLES) - # _____ Define and setup target ___ def target(*args): return entry_point, None + +def test_target(): + entry_point(["boe", ROM_PATH+"/rom4/rom4.gb"]) From arigo at codespeak.net Fri May 9 16:38:21 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 9 May 2008 16:38:21 +0200 (CEST) Subject: [pypy-svn] r54597 - pypy/dist/pypy/interpreter/astcompiler/test Message-ID: <20080509143821.AF8DC39B679@codespeak.net> Author: arigo Date: Fri May 9 16:38:19 2008 New Revision: 54597 Modified: pypy/dist/pypy/interpreter/astcompiler/test/test_ast.py Log: Fix tests. Modified: pypy/dist/pypy/interpreter/astcompiler/test/test_ast.py ============================================================================== --- pypy/dist/pypy/interpreter/astcompiler/test/test_ast.py (original) +++ pypy/dist/pypy/interpreter/astcompiler/test/test_ast.py Fri May 9 16:38:19 2008 @@ -1,6 +1,5 @@ from pypy.interpreter.astcompiler import ast#_temp as ast -from pypy.module.recparser.pyparser import source2ast -from pypy.interpreter.pyparser.test.test_astbuilder import FakeSpace +from pypy.interpreter.pyparser.test.test_astbuilder import source2ast class BaseVisitor(ast.ASTVisitor): def default(self, node): @@ -25,7 +24,7 @@ if a: b ''' - ast = source2ast(FakeSpace(), src) + ast = source2ast(src, 'exec') ast.mutate(BaseVisitor()) src = ''' try: @@ -33,20 +32,20 @@ except Exception: pass ''' - ast = source2ast(FakeSpace(), src) + ast = source2ast(src, 'exec') ast.mutate(BaseVisitor()) src = '{1:2}' - ast = source2ast(FakeSpace(), src) + ast = source2ast(src, 'exec') ast.mutate(BaseVisitor()) src = '1 > 3' - ast = source2ast(FakeSpace(), src) + ast = source2ast(src, 'exec') ast.mutate(BaseVisitor()) def test_mutate_elision(self): class ConstRemover(BaseVisitor): def visitConst(self, const): return None - listast = source2ast(FakeSpace(), "[1, 2]") + listast = source2ast("[1, 2]", 'exec') listast = listast.mutate(ConstRemover()) listnode = listast.node.nodes[0].expr assert isinstance(listnode, ast.List) From arigo at codespeak.net Fri May 9 17:38:31 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 9 May 2008 17:38:31 +0200 (CEST) Subject: [pypy-svn] r54598 - in pypy/dist/pypy/interpreter/pyparser: . test Message-ID: <20080509153831.A18CD39B679@codespeak.net> Author: arigo Date: Fri May 9 17:38:28 2008 New Revision: 54598 Modified: pypy/dist/pypy/interpreter/pyparser/ebnfparse.py pypy/dist/pypy/interpreter/pyparser/grammar.py pypy/dist/pypy/interpreter/pyparser/test/test_lookahead.py pypy/dist/pypy/interpreter/pyparser/test/test_pytokenizer.py Log: Remove the linear scan in GrammarElement.match_first_set, which was measured to consume over 6% of the total execution time of "pypy-c translate.py somesmalltarget". Modified: pypy/dist/pypy/interpreter/pyparser/ebnfparse.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/ebnfparse.py (original) +++ pypy/dist/pypy/interpreter/pyparser/ebnfparse.py Fri May 9 17:38:28 2008 @@ -29,6 +29,8 @@ class NameToken(Token): """A token that is not a keyword""" + isKeyword = False + def __init__(self, parser): Token.__init__(self, parser, parser.tokens['NAME']) @@ -56,8 +58,7 @@ def match_token(self, builder, other): - """special case of match token for tokens which are really keywords - """ + # Historical stuff. Might be useful for debugging. if not isinstance(other, Token): raise RuntimeError("Unexpected token type") if other is self.parser.EmptyToken: Modified: pypy/dist/pypy/interpreter/pyparser/grammar.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/grammar.py (original) +++ pypy/dist/pypy/interpreter/pyparser/grammar.py Fri May 9 17:38:28 2008 @@ -192,7 +192,8 @@ # integer mapping to either a token value or rule symbol value self.codename = codename self.args = [] - self.first_set = [] + self.first_set = {} + self.emptytoken_in_first_set = False self._trace = False def is_root(self): @@ -223,9 +224,9 @@ token = source.peek() if self._trace: pos1 = source.get_pos() - in_first_set = self.match_first_set(builder, token) - if not in_first_set: # and not EmptyToken in self.first_set: - if self.parser.EmptyToken in self.first_set: + in_first_set = self.match_first_set(token) + if not in_first_set: + if self.emptytoken_in_first_set: ret = builder.sequence(self, source, 0 ) if self._trace: self._debug_display(token, level, 'eee' ) @@ -315,17 +316,51 @@ # XXX: first_set could probably be implemented with sets return [] - def match_first_set(self, builder, other): - """matching is not equality: - token('NAME','x') matches token('NAME',None) - """ + def optimize_first_set(self): + """Precompute a data structure that optimizes match_first_set(). + The first_set attribute should no longer be needed after this. + """ + self.emptytoken_in_first_set = self.parser.EmptyToken in self.first_set + # see match_first_set() for the way this _match_cache is supposed + # to be used + self._match_cache = [GrammarElement._EMPTY_CODENAME_SET, # share empty + GrammarElement._EMPTY_CODENAME_SET] # dicts for tk in self.first_set: - if tk.match_token(builder, other): - return True - return False + if tk is not self.parser.EmptyToken: + cache = self._match_cache[tk.isKeyword] + if not cache: + cache = self._match_cache[tk.isKeyword] = {} # new dict + if tk.value is None: + cache[tk.codename] = None # match any value + else: + values = cache.setdefault(tk.codename, {}) + if values is None: + pass # already seen another tk matching any value + else: + values[tk.value] = None # add tk.value to the set + + _EMPTY_CODENAME_SET = {} + _EMPTY_VALUES_SET = {} - def in_first_set(self, other): - return other in self.first_set + def match_first_set(self, other): + """matching is not equality: + token('NAME','x') matches token('NAME',None). + + More precisely, for a match, we need to find a tk in self.first_set + for which all the following is true: + - other is not EmptyToken + - other.isKeyword == tk.isKeyword + - other.codename == tk.codename + - other.value == tk.value or tk.value is None + """ + try: + cachelist = self._match_cache + except AttributeError: + return True # not computed yet + cache = cachelist[other.isKeyword] + values = cache.get(other.codename, GrammarElement._EMPTY_VALUES_SET) + return (values is None or # 'None' means 'matches anything' + other.value in values) # otherwise, ok only if in the set def reorder_rule(self): """Called after the computation of first set to allow rules to be @@ -377,7 +412,7 @@ # to see if this solve our problems with infinite recursion for rule in self.args: if USE_LOOKAHEAD: - if not rule.match_first_set(builder, tok) and self.parser.EmptyToken not in rule.first_set: + if not rule.match_first_set(tok) and not rule.emptytoken_in_first_set: if self._trace: print "Skipping impossible rule: %s" % (rule,) continue @@ -406,9 +441,7 @@ # do this to avoid problems on indirect recursive rules for rule in self.args: for t in rule.first_set: - if t not in self.first_set: - self.first_set.append(t) - # self.first_set[t] = 1 + self.first_set[t] = None def reorder_rule(self): # take the opportunity to reorder rules in alternatives @@ -508,14 +541,10 @@ if not rule.first_set: break if self.parser.EmptyToken in self.first_set: - self.first_set.remove( self.parser.EmptyToken ) - - # del self.first_set[self.parser.EmptyToken] + del self.first_set[self.parser.EmptyToken] # while we're in this loop, keep agregating possible tokens for t in rule.first_set: - if t not in self.first_set: - self.first_set.append(t) - # self.first_set[t] = 1 + self.first_set[t] = None if self.parser.EmptyToken not in rule.first_set: break @@ -545,8 +574,7 @@ self.max = _max self.star = "x" if self.min == 0: - self.first_set.append( self.parser.EmptyToken ) - # self.first_set[self.parser.EmptyToken] = 1 + self.first_set[self.parser.EmptyToken] = None def _match(self, source, builder, level=0): """matches a number of times self.args[0]. the number must be @@ -607,11 +635,9 @@ LAH(S) = LAH(A) """ rule = self.args[0] - self.first_set = rule.first_set[:] - # self.first_set = dict(rule.first_set) - if self.min == 0 and self.parser.EmptyToken not in self.first_set: - self.first_set.append(self.parser.EmptyToken) - # self.first_set[self.parser.EmptyToken] = 1 + self.first_set = rule.first_set.copy() + if self.min == 0: + self.first_set[self.parser.EmptyToken] = None def validate( self, syntax_node ): """validate a syntax tree/subtree from this grammar node""" @@ -634,8 +660,7 @@ def __init__(self, parser, codename, value=None): GrammarElement.__init__(self, parser, codename) self.value = value - self.first_set = [self] - # self.first_set = {self: 1} + self.first_set = {self: None} def match(self, source, builder, level=0): """Matches a token. @@ -675,13 +700,7 @@ return "<%s>=='%s'" % (name, self.value) def match_token(self, builder, other): - """convenience '==' implementation, this is *not* a *real* equality test - a Token instance can be compared to: - - another Token instance in which case all fields (name and value) - must be equal - - a tuple, such as those yielded by the Python lexer, in which case - the comparison algorithm is similar to the one in match() - """ + # Historical stuff. Might be useful for debugging. if not isinstance(other, Token): raise RuntimeError("Unexpected token type") if other is self.parser.EmptyToken: @@ -689,8 +708,15 @@ res = other.isKeyword and other.codename == self.codename and self.value in [None, other.value] return res - def __eq__(self, other): + #def __eq__(self, other): + # XXX disabled to avoid strange differences between Python and RPython. + # XXX (moreover, only implementing __eq__ without __ne__ and __hash__ + # XXX is a bit fragile) + # return self.codename == other.codename and self.value == other.value + + def eq(self, other): return self.codename == other.codename and self.value == other.value + # XXX probably also "and self.isKeyword == other.isKeyword" def calc_first_set(self): """computes the list of possible next tokens @@ -801,6 +827,8 @@ for r in rules: assert len(r.first_set) > 0, "Error: ot Empty firstset for %s" % r r.reorder_rule() + for r in rules: + r.optimize_first_set() def build_alternative( self, name_id, args ): Modified: pypy/dist/pypy/interpreter/pyparser/test/test_lookahead.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/test/test_lookahead.py (original) +++ pypy/dist/pypy/interpreter/pyparser/test/test_lookahead.py Fri May 9 17:38:28 2008 @@ -12,59 +12,62 @@ self.parser.build_first_sets() def test_basic_token(self): - assert self.tok1.first_set == [self.tok1] + assert self.tok1.first_set == {self.tok1: None} def test_basic_alternative(self): alt = self.parser.Alternative_n("a1t", self.tokens) self.parser.build_first_sets() - assert alt.first_set == self.tokens + assert alt.first_set == dict.fromkeys(self.tokens) def test_basic_sequence(self): seq = self.parser.Sequence_n("seq", self.tokens) self.parser.build_first_sets() - assert seq.first_set == [self.tokens[0]] + assert seq.first_set == {self.tokens[0]: None} def test_basic_kleenstar(self): tok1, tok2, tok3 = self.tokens kstar1 = self.parser.KleeneStar_n("k", 1, 3, tok1) kstar2 = self.parser.KleeneStar_n("k2", 0, 3, tok1) self.parser.build_first_sets() - assert kstar1.first_set == [tok1] - assert kstar2.first_set == [tok1, self.parser.EmptyToken] + assert kstar1.first_set == {tok1: None} + assert kstar2.first_set == {tok1: None, + self.parser.EmptyToken: None} def test_maybe_empty_sequence(self): """S -> tok1{0,2} tok2{0,2} - ==> S.first_set = [tok1, tok2, EmptyToken] + ==> S.first_set = {tok1, tok2, EmptyToken} """ tok1, tok2, tok3 = self.tokens k1 = self.parser.KleeneStar_n( "k1", 0, 2, tok1) k2 = self.parser.KleeneStar_n("k2", 0, 2, tok2) seq = self.parser.Sequence_n( "seq", [k1, k2]) self.parser.build_first_sets() - assert seq.first_set == [tok1, tok2, self.parser.EmptyToken] + assert seq.first_set == {tok1: None, + tok2: None, + self.parser.EmptyToken: None} def test_not_empty_sequence(self): """S -> tok1{0,2} tok2{1,2} - ==> S.first_set = [tok1, tok2] + ==> S.first_set = {tok1, tok2} """ tok1, tok2, tok3 = self.tokens k1 = self.parser.KleeneStar_n("k1", 0, 2, tok1) k2 = self.parser.KleeneStar_n("k2", 1, 2, tok2) seq = self.parser.Sequence_n("seq", [k1, k2]) self.parser.build_first_sets() - assert seq.first_set == [tok1, tok2] + assert seq.first_set == {tok1: None, tok2: None} def test_token_comparison(self): tok1 = self.parser.Token_n( "tok1", "foo" ) tok1b = self.parser.Token_n( "tok1", "foo" ) tok2 = self.parser.Token_n( "tok2", "foo" ) tok3 = self.parser.Token_n( "tok2", None ) - assert tok1 == tok1b - assert tok1 != tok2 - assert tok2 != tok3 + assert tok1.eq(tok1b) + assert not tok1.eq(tok2) + assert not tok2.eq(tok3) @@ -86,7 +89,10 @@ p = self.parser LOW = p.tokens['LOW'] CAP = p.tokens['CAP'] - for s in [Token(p, LOW, 'low'), p.EmptyToken, Token(p, CAP, 'cap')]: - assert s in self.A.first_set - assert s in self.B.first_set - assert s in self.C.first_set + assert self.A.emptytoken_in_first_set + assert self.B.emptytoken_in_first_set + assert self.C.emptytoken_in_first_set + for s in [Token(p, LOW, 'low'), Token(p, CAP, 'cap')]: + assert self.A.match_first_set(s) + assert self.B.match_first_set(s) + assert self.C.match_first_set(s) Modified: pypy/dist/pypy/interpreter/pyparser/test/test_pytokenizer.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/test/test_pytokenizer.py (original) +++ pypy/dist/pypy/interpreter/pyparser/test/test_pytokenizer.py Fri May 9 17:38:28 2008 @@ -53,29 +53,38 @@ 'j', '0xg', '0xj', '0xJ', ] +def listeq(lst1, lst2): + if len(lst1) != len(lst2): + return False + for tk1, tk2 in zip(lst1, lst2): + if not tk1.eq(tk2): + return False + return True + def test_several_lines_list(): """tests list definition on several lines""" s = """['a' ]""" tokens = parse_source(s) - assert tokens[:4] == [Token(P, LSQB, None), Token(P, STRING, "'a'"), - Token(P, RSQB, None), Token(P, NEWLINE, '')] + assert listeq(tokens[:4], [Token(P, LSQB, None), Token(P, STRING, "'a'"), + Token(P, RSQB, None), Token(P, NEWLINE, '')]) def test_numbers(): """make sure all kind of numbers are correctly parsed""" for number in NUMBERS: - assert parse_source(number)[0] == Token(P, NUMBER, number) + assert parse_source(number)[0].eq(Token(P, NUMBER, number)) neg = '-%s' % number - assert parse_source(neg)[:2] == [Token(P, MINUS, None), - Token(P, NUMBER, number)] + assert listeq(parse_source(neg)[:2], [Token(P, MINUS, None), + Token(P, NUMBER, number)]) for number in BAD_NUMBERS: - assert parse_source(number)[0] != Token(P, NUMBER, number) + assert not parse_source(number)[0].eq(Token(P, NUMBER, number)) def test_hex_number(): """basic pasrse""" tokens = parse_source("a = 0x12L") - assert tokens[:4] == [Token(P, NAME, 'a'), Token(P, EQUAL, None), - Token(P, NUMBER, '0x12L'), Token(P, NEWLINE, '')] + assert listeq(tokens[:4], [Token(P, NAME, 'a'), Token(P, EQUAL, None), + Token(P, NUMBER, '0x12L'), + Token(P, NEWLINE, '')]) def test_punct(): """make sure each punctuation is correctly parsed""" From arigo at codespeak.net Fri May 9 17:40:13 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 9 May 2008 17:40:13 +0200 (CEST) Subject: [pypy-svn] r54599 - in pypy/branch/gc-tweak/pypy/interpreter/pyparser: . test Message-ID: <20080509154013.EFF3A39B68D@codespeak.net> Author: arigo Date: Fri May 9 17:40:11 2008 New Revision: 54599 Modified: pypy/branch/gc-tweak/pypy/interpreter/pyparser/ebnfparse.py pypy/branch/gc-tweak/pypy/interpreter/pyparser/grammar.py pypy/branch/gc-tweak/pypy/interpreter/pyparser/test/test_lookahead.py pypy/branch/gc-tweak/pypy/interpreter/pyparser/test/test_pytokenizer.py Log: Merge r54598 from the trunk. Modified: pypy/branch/gc-tweak/pypy/interpreter/pyparser/ebnfparse.py ============================================================================== --- pypy/branch/gc-tweak/pypy/interpreter/pyparser/ebnfparse.py (original) +++ pypy/branch/gc-tweak/pypy/interpreter/pyparser/ebnfparse.py Fri May 9 17:40:11 2008 @@ -29,6 +29,8 @@ class NameToken(Token): """A token that is not a keyword""" + isKeyword = False + def __init__(self, parser): Token.__init__(self, parser, parser.tokens['NAME']) @@ -56,8 +58,7 @@ def match_token(self, builder, other): - """special case of match token for tokens which are really keywords - """ + # Historical stuff. Might be useful for debugging. if not isinstance(other, Token): raise RuntimeError("Unexpected token type") if other is self.parser.EmptyToken: Modified: pypy/branch/gc-tweak/pypy/interpreter/pyparser/grammar.py ============================================================================== --- pypy/branch/gc-tweak/pypy/interpreter/pyparser/grammar.py (original) +++ pypy/branch/gc-tweak/pypy/interpreter/pyparser/grammar.py Fri May 9 17:40:11 2008 @@ -192,7 +192,8 @@ # integer mapping to either a token value or rule symbol value self.codename = codename self.args = [] - self.first_set = [] + self.first_set = {} + self.emptytoken_in_first_set = False self._trace = False def is_root(self): @@ -223,9 +224,9 @@ token = source.peek() if self._trace: pos1 = source.get_pos() - in_first_set = self.match_first_set(builder, token) - if not in_first_set: # and not EmptyToken in self.first_set: - if self.parser.EmptyToken in self.first_set: + in_first_set = self.match_first_set(token) + if not in_first_set: + if self.emptytoken_in_first_set: ret = builder.sequence(self, source, 0 ) if self._trace: self._debug_display(token, level, 'eee' ) @@ -315,17 +316,51 @@ # XXX: first_set could probably be implemented with sets return [] - def match_first_set(self, builder, other): - """matching is not equality: - token('NAME','x') matches token('NAME',None) - """ + def optimize_first_set(self): + """Precompute a data structure that optimizes match_first_set(). + The first_set attribute should no longer be needed after this. + """ + self.emptytoken_in_first_set = self.parser.EmptyToken in self.first_set + # see match_first_set() for the way this _match_cache is supposed + # to be used + self._match_cache = [GrammarElement._EMPTY_CODENAME_SET, # share empty + GrammarElement._EMPTY_CODENAME_SET] # dicts for tk in self.first_set: - if tk.match_token(builder, other): - return True - return False + if tk is not self.parser.EmptyToken: + cache = self._match_cache[tk.isKeyword] + if not cache: + cache = self._match_cache[tk.isKeyword] = {} # new dict + if tk.value is None: + cache[tk.codename] = None # match any value + else: + values = cache.setdefault(tk.codename, {}) + if values is None: + pass # already seen another tk matching any value + else: + values[tk.value] = None # add tk.value to the set + + _EMPTY_CODENAME_SET = {} + _EMPTY_VALUES_SET = {} - def in_first_set(self, other): - return other in self.first_set + def match_first_set(self, other): + """matching is not equality: + token('NAME','x') matches token('NAME',None). + + More precisely, for a match, we need to find a tk in self.first_set + for which all the following is true: + - other is not EmptyToken + - other.isKeyword == tk.isKeyword + - other.codename == tk.codename + - other.value == tk.value or tk.value is None + """ + try: + cachelist = self._match_cache + except AttributeError: + return True # not computed yet + cache = cachelist[other.isKeyword] + values = cache.get(other.codename, GrammarElement._EMPTY_VALUES_SET) + return (values is None or # 'None' means 'matches anything' + other.value in values) # otherwise, ok only if in the set def reorder_rule(self): """Called after the computation of first set to allow rules to be @@ -377,7 +412,7 @@ # to see if this solve our problems with infinite recursion for rule in self.args: if USE_LOOKAHEAD: - if not rule.match_first_set(builder, tok) and self.parser.EmptyToken not in rule.first_set: + if not rule.match_first_set(tok) and not rule.emptytoken_in_first_set: if self._trace: print "Skipping impossible rule: %s" % (rule,) continue @@ -406,9 +441,7 @@ # do this to avoid problems on indirect recursive rules for rule in self.args: for t in rule.first_set: - if t not in self.first_set: - self.first_set.append(t) - # self.first_set[t] = 1 + self.first_set[t] = None def reorder_rule(self): # take the opportunity to reorder rules in alternatives @@ -508,14 +541,10 @@ if not rule.first_set: break if self.parser.EmptyToken in self.first_set: - self.first_set.remove( self.parser.EmptyToken ) - - # del self.first_set[self.parser.EmptyToken] + del self.first_set[self.parser.EmptyToken] # while we're in this loop, keep agregating possible tokens for t in rule.first_set: - if t not in self.first_set: - self.first_set.append(t) - # self.first_set[t] = 1 + self.first_set[t] = None if self.parser.EmptyToken not in rule.first_set: break @@ -545,8 +574,7 @@ self.max = _max self.star = "x" if self.min == 0: - self.first_set.append( self.parser.EmptyToken ) - # self.first_set[self.parser.EmptyToken] = 1 + self.first_set[self.parser.EmptyToken] = None def _match(self, source, builder, level=0): """matches a number of times self.args[0]. the number must be @@ -607,11 +635,9 @@ LAH(S) = LAH(A) """ rule = self.args[0] - self.first_set = rule.first_set[:] - # self.first_set = dict(rule.first_set) - if self.min == 0 and self.parser.EmptyToken not in self.first_set: - self.first_set.append(self.parser.EmptyToken) - # self.first_set[self.parser.EmptyToken] = 1 + self.first_set = rule.first_set.copy() + if self.min == 0: + self.first_set[self.parser.EmptyToken] = None def validate( self, syntax_node ): """validate a syntax tree/subtree from this grammar node""" @@ -634,8 +660,7 @@ def __init__(self, parser, codename, value=None): GrammarElement.__init__(self, parser, codename) self.value = value - self.first_set = [self] - # self.first_set = {self: 1} + self.first_set = {self: None} def match(self, source, builder, level=0): """Matches a token. @@ -675,13 +700,7 @@ return "<%s>=='%s'" % (name, self.value) def match_token(self, builder, other): - """convenience '==' implementation, this is *not* a *real* equality test - a Token instance can be compared to: - - another Token instance in which case all fields (name and value) - must be equal - - a tuple, such as those yielded by the Python lexer, in which case - the comparison algorithm is similar to the one in match() - """ + # Historical stuff. Might be useful for debugging. if not isinstance(other, Token): raise RuntimeError("Unexpected token type") if other is self.parser.EmptyToken: @@ -689,8 +708,15 @@ res = other.isKeyword and other.codename == self.codename and self.value in [None, other.value] return res - def __eq__(self, other): + #def __eq__(self, other): + # XXX disabled to avoid strange differences between Python and RPython. + # XXX (moreover, only implementing __eq__ without __ne__ and __hash__ + # XXX is a bit fragile) + # return self.codename == other.codename and self.value == other.value + + def eq(self, other): return self.codename == other.codename and self.value == other.value + # XXX probably also "and self.isKeyword == other.isKeyword" def calc_first_set(self): """computes the list of possible next tokens @@ -801,6 +827,8 @@ for r in rules: assert len(r.first_set) > 0, "Error: ot Empty firstset for %s" % r r.reorder_rule() + for r in rules: + r.optimize_first_set() def build_alternative( self, name_id, args ): Modified: pypy/branch/gc-tweak/pypy/interpreter/pyparser/test/test_lookahead.py ============================================================================== --- pypy/branch/gc-tweak/pypy/interpreter/pyparser/test/test_lookahead.py (original) +++ pypy/branch/gc-tweak/pypy/interpreter/pyparser/test/test_lookahead.py Fri May 9 17:40:11 2008 @@ -12,59 +12,62 @@ self.parser.build_first_sets() def test_basic_token(self): - assert self.tok1.first_set == [self.tok1] + assert self.tok1.first_set == {self.tok1: None} def test_basic_alternative(self): alt = self.parser.Alternative_n("a1t", self.tokens) self.parser.build_first_sets() - assert alt.first_set == self.tokens + assert alt.first_set == dict.fromkeys(self.tokens) def test_basic_sequence(self): seq = self.parser.Sequence_n("seq", self.tokens) self.parser.build_first_sets() - assert seq.first_set == [self.tokens[0]] + assert seq.first_set == {self.tokens[0]: None} def test_basic_kleenstar(self): tok1, tok2, tok3 = self.tokens kstar1 = self.parser.KleeneStar_n("k", 1, 3, tok1) kstar2 = self.parser.KleeneStar_n("k2", 0, 3, tok1) self.parser.build_first_sets() - assert kstar1.first_set == [tok1] - assert kstar2.first_set == [tok1, self.parser.EmptyToken] + assert kstar1.first_set == {tok1: None} + assert kstar2.first_set == {tok1: None, + self.parser.EmptyToken: None} def test_maybe_empty_sequence(self): """S -> tok1{0,2} tok2{0,2} - ==> S.first_set = [tok1, tok2, EmptyToken] + ==> S.first_set = {tok1, tok2, EmptyToken} """ tok1, tok2, tok3 = self.tokens k1 = self.parser.KleeneStar_n( "k1", 0, 2, tok1) k2 = self.parser.KleeneStar_n("k2", 0, 2, tok2) seq = self.parser.Sequence_n( "seq", [k1, k2]) self.parser.build_first_sets() - assert seq.first_set == [tok1, tok2, self.parser.EmptyToken] + assert seq.first_set == {tok1: None, + tok2: None, + self.parser.EmptyToken: None} def test_not_empty_sequence(self): """S -> tok1{0,2} tok2{1,2} - ==> S.first_set = [tok1, tok2] + ==> S.first_set = {tok1, tok2} """ tok1, tok2, tok3 = self.tokens k1 = self.parser.KleeneStar_n("k1", 0, 2, tok1) k2 = self.parser.KleeneStar_n("k2", 1, 2, tok2) seq = self.parser.Sequence_n("seq", [k1, k2]) self.parser.build_first_sets() - assert seq.first_set == [tok1, tok2] + assert seq.first_set == {tok1: None, tok2: None} def test_token_comparison(self): tok1 = self.parser.Token_n( "tok1", "foo" ) tok1b = self.parser.Token_n( "tok1", "foo" ) tok2 = self.parser.Token_n( "tok2", "foo" ) tok3 = self.parser.Token_n( "tok2", None ) - assert tok1 == tok1b - assert tok1 != tok2 - assert tok2 != tok3 + assert tok1.eq(tok1b) + assert not tok1.eq(tok2) + assert not tok2.eq(tok3) @@ -86,7 +89,10 @@ p = self.parser LOW = p.tokens['LOW'] CAP = p.tokens['CAP'] - for s in [Token(p, LOW, 'low'), p.EmptyToken, Token(p, CAP, 'cap')]: - assert s in self.A.first_set - assert s in self.B.first_set - assert s in self.C.first_set + assert self.A.emptytoken_in_first_set + assert self.B.emptytoken_in_first_set + assert self.C.emptytoken_in_first_set + for s in [Token(p, LOW, 'low'), Token(p, CAP, 'cap')]: + assert self.A.match_first_set(s) + assert self.B.match_first_set(s) + assert self.C.match_first_set(s) Modified: pypy/branch/gc-tweak/pypy/interpreter/pyparser/test/test_pytokenizer.py ============================================================================== --- pypy/branch/gc-tweak/pypy/interpreter/pyparser/test/test_pytokenizer.py (original) +++ pypy/branch/gc-tweak/pypy/interpreter/pyparser/test/test_pytokenizer.py Fri May 9 17:40:11 2008 @@ -53,29 +53,38 @@ 'j', '0xg', '0xj', '0xJ', ] +def listeq(lst1, lst2): + if len(lst1) != len(lst2): + return False + for tk1, tk2 in zip(lst1, lst2): + if not tk1.eq(tk2): + return False + return True + def test_several_lines_list(): """tests list definition on several lines""" s = """['a' ]""" tokens = parse_source(s) - assert tokens[:4] == [Token(P, LSQB, None), Token(P, STRING, "'a'"), - Token(P, RSQB, None), Token(P, NEWLINE, '')] + assert listeq(tokens[:4], [Token(P, LSQB, None), Token(P, STRING, "'a'"), + Token(P, RSQB, None), Token(P, NEWLINE, '')]) def test_numbers(): """make sure all kind of numbers are correctly parsed""" for number in NUMBERS: - assert parse_source(number)[0] == Token(P, NUMBER, number) + assert parse_source(number)[0].eq(Token(P, NUMBER, number)) neg = '-%s' % number - assert parse_source(neg)[:2] == [Token(P, MINUS, None), - Token(P, NUMBER, number)] + assert listeq(parse_source(neg)[:2], [Token(P, MINUS, None), + Token(P, NUMBER, number)]) for number in BAD_NUMBERS: - assert parse_source(number)[0] != Token(P, NUMBER, number) + assert not parse_source(number)[0].eq(Token(P, NUMBER, number)) def test_hex_number(): """basic pasrse""" tokens = parse_source("a = 0x12L") - assert tokens[:4] == [Token(P, NAME, 'a'), Token(P, EQUAL, None), - Token(P, NUMBER, '0x12L'), Token(P, NEWLINE, '')] + assert listeq(tokens[:4], [Token(P, NAME, 'a'), Token(P, EQUAL, None), + Token(P, NUMBER, '0x12L'), + Token(P, NEWLINE, '')]) def test_punct(): """make sure each punctuation is correctly parsed""" From arigo at codespeak.net Fri May 9 18:27:24 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 9 May 2008 18:27:24 +0200 (CEST) Subject: [pypy-svn] r54600 - in pypy/dist/pypy/rpython: . lltypesystem ootypesystem test Message-ID: <20080509162724.3E077169E4A@codespeak.net> Author: arigo Date: Fri May 9 18:27:23 2008 New Revision: 54600 Modified: pypy/dist/pypy/rpython/lltypesystem/rclass.py pypy/dist/pypy/rpython/ootypesystem/rclass.py pypy/dist/pypy/rpython/rclass.py pypy/dist/pypy/rpython/test/test_rclass.py Log: Another circularity bug in the rtyper that was here forever but never triggered so far, involving a cycle like "dictionary -> RPython instance as a key -> dictionary". Modified: pypy/dist/pypy/rpython/lltypesystem/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rclass.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rclass.py Fri May 9 18:27:23 2008 @@ -408,17 +408,16 @@ else: return self.rbase.get_ll_hash_function() - def initialize_prebuilt_instance(self, value, classdef, result): + def initialize_prebuilt_data(self, value, classdef, result): if self.classdef is not None: # recursively build the parent part of the instance - self.rbase.initialize_prebuilt_instance(value, classdef, - result.super) + self.rbase.initialize_prebuilt_data(value, classdef, result.super) # then add instance attributes from this level for name, (mangled_name, r) in self.fields.items(): if r.lowleveltype is Void: llattrvalue = None elif name == '_hash_cache_': # hash() support - llattrvalue = hash(value) + continue # already done by initialize_prebuilt_hash() else: try: attrvalue = getattr(value, name) @@ -438,6 +437,14 @@ rclass = getclassrepr(self.rtyper, classdef) result.typeptr = rclass.getvtable() + def initialize_prebuilt_hash(self, value, result): + if self.classdef is not None: + self.rbase.initialize_prebuilt_hash(value, result.super) + if '_hash_cache_' in self.fields: + mangled_name, r = self.fields['_hash_cache_'] + llattrvalue = hash(value) + setattr(result, mangled_name, llattrvalue) + def getfieldrepr(self, attr): """Return the repr used for the given attribute.""" if attr in self.fields: Modified: pypy/dist/pypy/rpython/ootypesystem/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/ootypesystem/rclass.py (original) +++ pypy/dist/pypy/rpython/ootypesystem/rclass.py Fri May 9 18:27:23 2008 @@ -471,7 +471,7 @@ resulttype=ootype.Void) return v_instance - def initialize_prebuilt_instance(self, value, classdef, result): + def initialize_prebuilt_data(self, value, classdef, result): # then add instance attributes from this level classrepr = getclassrepr(self.rtyper, self.classdef) for mangled, (oot, default) in self.lowleveltype._allfields().items(): @@ -480,7 +480,7 @@ elif mangled == 'meta': llattrvalue = classrepr.get_meta_instance() elif mangled == '_hash_cache_': # hash() support - llattrvalue = hash(value) + continue # already done by initialize_prebuilt_hash() else: name = unmangle(mangled, self.rtyper.getconfig()) try: @@ -496,6 +496,10 @@ llattrvalue = self.allfields[mangled].convert_const(attrvalue) setattr(result, mangled, llattrvalue) + def initialize_prebuilt_hash(self, value, result): + if '_hash_cache_' in self.lowleveltype._allfields(): + result._hash_cache_ = hash(value) + buildinstancerepr = InstanceRepr Modified: pypy/dist/pypy/rpython/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/rclass.py (original) +++ pypy/dist/pypy/rpython/rclass.py Fri May 9 18:27:23 2008 @@ -167,6 +167,12 @@ self.initialize_prebuilt_instance(Ellipsis, self.classdef, result) return result + def initialize_prebuilt_instance(self, value, classdef, result): + # must fill in the _hash_cache_ field before the other ones + # (see test_circular_hash_initialization) + self.initialize_prebuilt_hash(value, result) + self.initialize_prebuilt_data(value, classdef, result) + def rtype_type(self, hop): raise NotImplementedError Modified: pypy/dist/pypy/rpython/test/test_rclass.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rclass.py (original) +++ pypy/dist/pypy/rpython/test/test_rclass.py Fri May 9 18:27:23 2008 @@ -412,7 +412,21 @@ # relevant on top of the ootypesystem though. assert res.item2 == hash(c) assert res.item3 == hash(d) - + + def test_circular_hash_initialization(self): + class B: + pass + class C(B): + pass + c1 = C() + c1.somedict = {c1: True, C(): False} + def f(): + B().somedict = {} # force the attribute up + c1.somedict[c1] = 123 + return len(c1.somedict) + res = self.interpret(f, []) + assert res == 2 + def test_type(self): class A: pass From arigo at codespeak.net Fri May 9 18:29:19 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 9 May 2008 18:29:19 +0200 (CEST) Subject: [pypy-svn] r54601 - in pypy/dist/pypy/interpreter/pyparser: . test Message-ID: <20080509162919.95A2F169E6F@codespeak.net> Author: arigo Date: Fri May 9 18:29:19 2008 New Revision: 54601 Modified: pypy/dist/pypy/interpreter/pyparser/grammar.py pypy/dist/pypy/interpreter/pyparser/test/test_lookahead.py Log: Trying to reduce another major wastefulness in this code, probably naively. This avoids creating a new dict and a new list every time a Token is instantiated. Also added an _attrs_ to ensure unexpected attributes don't show up. Modified: pypy/dist/pypy/interpreter/pyparser/grammar.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/grammar.py (original) +++ pypy/dist/pypy/interpreter/pyparser/grammar.py Fri May 9 18:29:19 2008 @@ -183,18 +183,23 @@ class GrammarElement(Wrappable): """Base parser class""" + _trace = False + first_set = None + emptytoken_in_first_set = False + _match_cache = None + args = [] + symbols = {} # dirty trick to provide a symbols mapping while printing (and not putting it in every object) + _attrs_ = ['parser', 'codename', 'args', + 'first_set', 'emptytoken_in_first_set', '_match_cache'] + def __init__(self, parser, codename): # the rule name assert isinstance(parser, Parser) self.parser = parser # integer mapping to either a token value or rule symbol value self.codename = codename - self.args = [] - self.first_set = {} - self.emptytoken_in_first_set = False - self._trace = False def is_root(self): """This is a root node of the grammar, that is one that will @@ -256,7 +261,7 @@ prefix = '%s%s' % (' ' * level, prefix) print prefix, " RULE =", self print prefix, " TOKEN =", token - print prefix, " FIRST SET =", self.first_set + print prefix, " FIRST SET =", getattr(self, 'first_set', 'none') def _match(self, source, builder, level=0): """Try to match a grammar rule @@ -313,8 +318,15 @@ """returns the list of possible next tokens *must* be implemented in subclasses """ - # XXX: first_set could probably be implemented with sets - return [] + pass + + def get_first_set(self): + if self.first_set is None: + self.initialize_first_set() + return self.first_set + + def initialize_first_set(self): + self.first_set = {} def optimize_first_set(self): """Precompute a data structure that optimizes match_first_set(). @@ -353,9 +365,8 @@ - other.codename == tk.codename - other.value == tk.value or tk.value is None """ - try: - cachelist = self._match_cache - except AttributeError: + cachelist = self._match_cache + if cachelist is None: return True # not computed yet cache = cachelist[other.isKeyword] values = cache.get(other.codename, GrammarElement._EMPTY_VALUES_SET) @@ -440,7 +451,7 @@ """ # do this to avoid problems on indirect recursive rules for rule in self.args: - for t in rule.first_set: + for t in rule.get_first_set(): self.first_set[t] = None def reorder_rule(self): @@ -538,7 +549,7 @@ LAH(S) = LAH(A) """ for rule in self.args: - if not rule.first_set: + if not rule.get_first_set(): break if self.parser.EmptyToken in self.first_set: del self.first_set[self.parser.EmptyToken] @@ -573,6 +584,9 @@ raise ValueError("KleeneStar needs max==-1 or max>1") self.max = _max self.star = "x" + + def initialize_first_set(self): + GrammarElement.initialize_first_set(self) if self.min == 0: self.first_set[self.parser.EmptyToken] = None @@ -635,7 +649,7 @@ LAH(S) = LAH(A) """ rule = self.args[0] - self.first_set = rule.first_set.copy() + self.first_set = rule.get_first_set().copy() if self.min == 0: self.first_set[self.parser.EmptyToken] = None @@ -657,9 +671,13 @@ class Token(GrammarElement): """Represents a Token in a grammar rule (a lexer token)""" isKeyword = True + _attrs_ = ['isKeyword', 'value'] + def __init__(self, parser, codename, value=None): GrammarElement.__init__(self, parser, codename) self.value = value + + def initialize_first_set(self): self.first_set = {self: None} def match(self, source, builder, level=0): @@ -813,6 +831,8 @@ full first sets. """ rules = self.all_rules + for r in rules: + r.initialize_first_set() changed = True while changed: # loop while one first set is changed Modified: pypy/dist/pypy/interpreter/pyparser/test/test_lookahead.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/test/test_lookahead.py (original) +++ pypy/dist/pypy/interpreter/pyparser/test/test_lookahead.py Fri May 9 18:29:19 2008 @@ -12,27 +12,27 @@ self.parser.build_first_sets() def test_basic_token(self): - assert self.tok1.first_set == {self.tok1: None} + assert self.tok1.get_first_set() == {self.tok1: None} def test_basic_alternative(self): alt = self.parser.Alternative_n("a1t", self.tokens) self.parser.build_first_sets() - assert alt.first_set == dict.fromkeys(self.tokens) + assert alt.get_first_set() == dict.fromkeys(self.tokens) def test_basic_sequence(self): seq = self.parser.Sequence_n("seq", self.tokens) self.parser.build_first_sets() - assert seq.first_set == {self.tokens[0]: None} + assert seq.get_first_set() == {self.tokens[0]: None} def test_basic_kleenstar(self): tok1, tok2, tok3 = self.tokens kstar1 = self.parser.KleeneStar_n("k", 1, 3, tok1) kstar2 = self.parser.KleeneStar_n("k2", 0, 3, tok1) self.parser.build_first_sets() - assert kstar1.first_set == {tok1: None} - assert kstar2.first_set == {tok1: None, - self.parser.EmptyToken: None} + assert kstar1.get_first_set() == {tok1: None} + assert kstar2.get_first_set() == {tok1: None, + self.parser.EmptyToken: None} def test_maybe_empty_sequence(self): @@ -44,9 +44,9 @@ k2 = self.parser.KleeneStar_n("k2", 0, 2, tok2) seq = self.parser.Sequence_n( "seq", [k1, k2]) self.parser.build_first_sets() - assert seq.first_set == {tok1: None, - tok2: None, - self.parser.EmptyToken: None} + assert seq.get_first_set() == {tok1: None, + tok2: None, + self.parser.EmptyToken: None} def test_not_empty_sequence(self): @@ -58,7 +58,7 @@ k2 = self.parser.KleeneStar_n("k2", 1, 2, tok2) seq = self.parser.Sequence_n("seq", [k1, k2]) self.parser.build_first_sets() - assert seq.first_set == {tok1: None, tok2: None} + assert seq.get_first_set() == {tok1: None, tok2: None} def test_token_comparison(self): tok1 = self.parser.Token_n( "tok1", "foo" ) From arigo at codespeak.net Fri May 9 18:30:36 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 9 May 2008 18:30:36 +0200 (CEST) Subject: [pypy-svn] r54602 - in pypy/branch/gc-tweak/pypy/rpython: . lltypesystem ootypesystem test Message-ID: <20080509163036.362CE169E6F@codespeak.net> Author: arigo Date: Fri May 9 18:30:35 2008 New Revision: 54602 Modified: pypy/branch/gc-tweak/pypy/rpython/lltypesystem/rclass.py pypy/branch/gc-tweak/pypy/rpython/ootypesystem/rclass.py pypy/branch/gc-tweak/pypy/rpython/rclass.py pypy/branch/gc-tweak/pypy/rpython/test/test_rclass.py Log: Merge r54600 from the trunk. Modified: pypy/branch/gc-tweak/pypy/rpython/lltypesystem/rclass.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/lltypesystem/rclass.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/lltypesystem/rclass.py Fri May 9 18:30:35 2008 @@ -408,17 +408,16 @@ else: return self.rbase.get_ll_hash_function() - def initialize_prebuilt_instance(self, value, classdef, result): + def initialize_prebuilt_data(self, value, classdef, result): if self.classdef is not None: # recursively build the parent part of the instance - self.rbase.initialize_prebuilt_instance(value, classdef, - result.super) + self.rbase.initialize_prebuilt_data(value, classdef, result.super) # then add instance attributes from this level for name, (mangled_name, r) in self.fields.items(): if r.lowleveltype is Void: llattrvalue = None elif name == '_hash_cache_': # hash() support - llattrvalue = hash(value) + continue # already done by initialize_prebuilt_hash() else: try: attrvalue = getattr(value, name) @@ -438,6 +437,14 @@ rclass = getclassrepr(self.rtyper, classdef) result.typeptr = rclass.getvtable() + def initialize_prebuilt_hash(self, value, result): + if self.classdef is not None: + self.rbase.initialize_prebuilt_hash(value, result.super) + if '_hash_cache_' in self.fields: + mangled_name, r = self.fields['_hash_cache_'] + llattrvalue = hash(value) + setattr(result, mangled_name, llattrvalue) + def getfieldrepr(self, attr): """Return the repr used for the given attribute.""" if attr in self.fields: Modified: pypy/branch/gc-tweak/pypy/rpython/ootypesystem/rclass.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/ootypesystem/rclass.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/ootypesystem/rclass.py Fri May 9 18:30:35 2008 @@ -471,7 +471,7 @@ resulttype=ootype.Void) return v_instance - def initialize_prebuilt_instance(self, value, classdef, result): + def initialize_prebuilt_data(self, value, classdef, result): # then add instance attributes from this level classrepr = getclassrepr(self.rtyper, self.classdef) for mangled, (oot, default) in self.lowleveltype._allfields().items(): @@ -480,7 +480,7 @@ elif mangled == 'meta': llattrvalue = classrepr.get_meta_instance() elif mangled == '_hash_cache_': # hash() support - llattrvalue = hash(value) + continue # already done by initialize_prebuilt_hash() else: name = unmangle(mangled, self.rtyper.getconfig()) try: @@ -496,6 +496,10 @@ llattrvalue = self.allfields[mangled].convert_const(attrvalue) setattr(result, mangled, llattrvalue) + def initialize_prebuilt_hash(self, value, result): + if '_hash_cache_' in self.lowleveltype._allfields(): + result._hash_cache_ = hash(value) + buildinstancerepr = InstanceRepr Modified: pypy/branch/gc-tweak/pypy/rpython/rclass.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/rclass.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/rclass.py Fri May 9 18:30:35 2008 @@ -167,6 +167,12 @@ self.initialize_prebuilt_instance(Ellipsis, self.classdef, result) return result + def initialize_prebuilt_instance(self, value, classdef, result): + # must fill in the _hash_cache_ field before the other ones + # (see test_circular_hash_initialization) + self.initialize_prebuilt_hash(value, result) + self.initialize_prebuilt_data(value, classdef, result) + def rtype_type(self, hop): raise NotImplementedError Modified: pypy/branch/gc-tweak/pypy/rpython/test/test_rclass.py ============================================================================== --- pypy/branch/gc-tweak/pypy/rpython/test/test_rclass.py (original) +++ pypy/branch/gc-tweak/pypy/rpython/test/test_rclass.py Fri May 9 18:30:35 2008 @@ -412,7 +412,21 @@ # relevant on top of the ootypesystem though. assert res.item2 == hash(c) assert res.item3 == hash(d) - + + def test_circular_hash_initialization(self): + class B: + pass + class C(B): + pass + c1 = C() + c1.somedict = {c1: True, C(): False} + def f(): + B().somedict = {} # force the attribute up + c1.somedict[c1] = 123 + return len(c1.somedict) + res = self.interpret(f, []) + assert res == 2 + def test_type(self): class A: pass From arigo at codespeak.net Fri May 9 18:30:43 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 9 May 2008 18:30:43 +0200 (CEST) Subject: [pypy-svn] r54603 - in pypy/branch/gc-tweak/pypy/interpreter/pyparser: . test Message-ID: <20080509163043.E66E6498074@codespeak.net> Author: arigo Date: Fri May 9 18:30:43 2008 New Revision: 54603 Modified: pypy/branch/gc-tweak/pypy/interpreter/pyparser/grammar.py pypy/branch/gc-tweak/pypy/interpreter/pyparser/test/test_lookahead.py Log: Merge r54601 from the trunk. Modified: pypy/branch/gc-tweak/pypy/interpreter/pyparser/grammar.py ============================================================================== --- pypy/branch/gc-tweak/pypy/interpreter/pyparser/grammar.py (original) +++ pypy/branch/gc-tweak/pypy/interpreter/pyparser/grammar.py Fri May 9 18:30:43 2008 @@ -183,18 +183,23 @@ class GrammarElement(Wrappable): """Base parser class""" + _trace = False + first_set = None + emptytoken_in_first_set = False + _match_cache = None + args = [] + symbols = {} # dirty trick to provide a symbols mapping while printing (and not putting it in every object) + _attrs_ = ['parser', 'codename', 'args', + 'first_set', 'emptytoken_in_first_set', '_match_cache'] + def __init__(self, parser, codename): # the rule name assert isinstance(parser, Parser) self.parser = parser # integer mapping to either a token value or rule symbol value self.codename = codename - self.args = [] - self.first_set = {} - self.emptytoken_in_first_set = False - self._trace = False def is_root(self): """This is a root node of the grammar, that is one that will @@ -256,7 +261,7 @@ prefix = '%s%s' % (' ' * level, prefix) print prefix, " RULE =", self print prefix, " TOKEN =", token - print prefix, " FIRST SET =", self.first_set + print prefix, " FIRST SET =", getattr(self, 'first_set', 'none') def _match(self, source, builder, level=0): """Try to match a grammar rule @@ -313,8 +318,15 @@ """returns the list of possible next tokens *must* be implemented in subclasses """ - # XXX: first_set could probably be implemented with sets - return [] + pass + + def get_first_set(self): + if self.first_set is None: + self.initialize_first_set() + return self.first_set + + def initialize_first_set(self): + self.first_set = {} def optimize_first_set(self): """Precompute a data structure that optimizes match_first_set(). @@ -353,9 +365,8 @@ - other.codename == tk.codename - other.value == tk.value or tk.value is None """ - try: - cachelist = self._match_cache - except AttributeError: + cachelist = self._match_cache + if cachelist is None: return True # not computed yet cache = cachelist[other.isKeyword] values = cache.get(other.codename, GrammarElement._EMPTY_VALUES_SET) @@ -440,7 +451,7 @@ """ # do this to avoid problems on indirect recursive rules for rule in self.args: - for t in rule.first_set: + for t in rule.get_first_set(): self.first_set[t] = None def reorder_rule(self): @@ -538,7 +549,7 @@ LAH(S) = LAH(A) """ for rule in self.args: - if not rule.first_set: + if not rule.get_first_set(): break if self.parser.EmptyToken in self.first_set: del self.first_set[self.parser.EmptyToken] @@ -573,6 +584,9 @@ raise ValueError("KleeneStar needs max==-1 or max>1") self.max = _max self.star = "x" + + def initialize_first_set(self): + GrammarElement.initialize_first_set(self) if self.min == 0: self.first_set[self.parser.EmptyToken] = None @@ -635,7 +649,7 @@ LAH(S) = LAH(A) """ rule = self.args[0] - self.first_set = rule.first_set.copy() + self.first_set = rule.get_first_set().copy() if self.min == 0: self.first_set[self.parser.EmptyToken] = None @@ -657,9 +671,13 @@ class Token(GrammarElement): """Represents a Token in a grammar rule (a lexer token)""" isKeyword = True + _attrs_ = ['isKeyword', 'value'] + def __init__(self, parser, codename, value=None): GrammarElement.__init__(self, parser, codename) self.value = value + + def initialize_first_set(self): self.first_set = {self: None} def match(self, source, builder, level=0): @@ -813,6 +831,8 @@ full first sets. """ rules = self.all_rules + for r in rules: + r.initialize_first_set() changed = True while changed: # loop while one first set is changed Modified: pypy/branch/gc-tweak/pypy/interpreter/pyparser/test/test_lookahead.py ============================================================================== --- pypy/branch/gc-tweak/pypy/interpreter/pyparser/test/test_lookahead.py (original) +++ pypy/branch/gc-tweak/pypy/interpreter/pyparser/test/test_lookahead.py Fri May 9 18:30:43 2008 @@ -12,27 +12,27 @@ self.parser.build_first_sets() def test_basic_token(self): - assert self.tok1.first_set == {self.tok1: None} + assert self.tok1.get_first_set() == {self.tok1: None} def test_basic_alternative(self): alt = self.parser.Alternative_n("a1t", self.tokens) self.parser.build_first_sets() - assert alt.first_set == dict.fromkeys(self.tokens) + assert alt.get_first_set() == dict.fromkeys(self.tokens) def test_basic_sequence(self): seq = self.parser.Sequence_n("seq", self.tokens) self.parser.build_first_sets() - assert seq.first_set == {self.tokens[0]: None} + assert seq.get_first_set() == {self.tokens[0]: None} def test_basic_kleenstar(self): tok1, tok2, tok3 = self.tokens kstar1 = self.parser.KleeneStar_n("k", 1, 3, tok1) kstar2 = self.parser.KleeneStar_n("k2", 0, 3, tok1) self.parser.build_first_sets() - assert kstar1.first_set == {tok1: None} - assert kstar2.first_set == {tok1: None, - self.parser.EmptyToken: None} + assert kstar1.get_first_set() == {tok1: None} + assert kstar2.get_first_set() == {tok1: None, + self.parser.EmptyToken: None} def test_maybe_empty_sequence(self): @@ -44,9 +44,9 @@ k2 = self.parser.KleeneStar_n("k2", 0, 2, tok2) seq = self.parser.Sequence_n( "seq", [k1, k2]) self.parser.build_first_sets() - assert seq.first_set == {tok1: None, - tok2: None, - self.parser.EmptyToken: None} + assert seq.get_first_set() == {tok1: None, + tok2: None, + self.parser.EmptyToken: None} def test_not_empty_sequence(self): @@ -58,7 +58,7 @@ k2 = self.parser.KleeneStar_n("k2", 1, 2, tok2) seq = self.parser.Sequence_n("seq", [k1, k2]) self.parser.build_first_sets() - assert seq.first_set == {tok1: None, tok2: None} + assert seq.get_first_set() == {tok1: None, tok2: None} def test_token_comparison(self): tok1 = self.parser.Token_n( "tok1", "foo" ) From arigo at codespeak.net Fri May 9 18:47:17 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 9 May 2008 18:47:17 +0200 (CEST) Subject: [pypy-svn] r54604 - pypy/dist/pypy/interpreter/pyparser Message-ID: <20080509164717.C0BA1498074@codespeak.net> Author: arigo Date: Fri May 9 18:47:14 2008 New Revision: 54604 Modified: pypy/dist/pypy/interpreter/pyparser/grammar.py Log: Translation fix. Modified: pypy/dist/pypy/interpreter/pyparser/grammar.py ============================================================================== --- pypy/dist/pypy/interpreter/pyparser/grammar.py (original) +++ pypy/dist/pypy/interpreter/pyparser/grammar.py Fri May 9 18:47:14 2008 @@ -370,8 +370,13 @@ return True # not computed yet cache = cachelist[other.isKeyword] values = cache.get(other.codename, GrammarElement._EMPTY_VALUES_SET) - return (values is None or # 'None' means 'matches anything' - other.value in values) # otherwise, ok only if in the set + if values is None: + return True # 'None' means 'matches anything' + elif other.value is None: + return False # because tk.value != None (for all tk) + else: + return other.value in values # otherwise, ok only if in the set + # XXX "None in dict" crashes after translation - needs to be fixed def reorder_rule(self): """Called after the computation of first set to allow rules to be From arigo at codespeak.net Fri May 9 19:07:11 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 9 May 2008 19:07:11 +0200 (CEST) Subject: [pypy-svn] r54605 - pypy/branch/gc-tweak/pypy/interpreter/pyparser Message-ID: <20080509170711.5B77D4981EA@codespeak.net> Author: arigo Date: Fri May 9 19:07:10 2008 New Revision: 54605 Modified: pypy/branch/gc-tweak/pypy/interpreter/pyparser/grammar.py Log: Merge r54604 from the trunk. Modified: pypy/branch/gc-tweak/pypy/interpreter/pyparser/grammar.py ============================================================================== --- pypy/branch/gc-tweak/pypy/interpreter/pyparser/grammar.py (original) +++ pypy/branch/gc-tweak/pypy/interpreter/pyparser/grammar.py Fri May 9 19:07:10 2008 @@ -370,8 +370,13 @@ return True # not computed yet cache = cachelist[other.isKeyword] values = cache.get(other.codename, GrammarElement._EMPTY_VALUES_SET) - return (values is None or # 'None' means 'matches anything' - other.value in values) # otherwise, ok only if in the set + if values is None: + return True # 'None' means 'matches anything' + elif other.value is None: + return False # because tk.value != None (for all tk) + else: + return other.value in values # otherwise, ok only if in the set + # XXX "None in dict" crashes after translation - needs to be fixed def reorder_rule(self): """Called after the computation of first set to allow rules to be From arigo at codespeak.net Fri May 9 19:52:35 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 9 May 2008 19:52:35 +0200 (CEST) Subject: [pypy-svn] r54607 - pypy/dist/pypy/lib Message-ID: <20080509175235.EA17216A07E@codespeak.net> Author: arigo Date: Fri May 9 19:52:33 2008 New Revision: 54607 Modified: pypy/dist/pypy/lib/_locale.py Log: This is still incomplete and causes more troubles than if it was just absent. Disable it for now... Modified: pypy/dist/pypy/lib/_locale.py ============================================================================== --- pypy/dist/pypy/lib/_locale.py (original) +++ pypy/dist/pypy/lib/_locale.py Fri May 9 19:52:33 2008 @@ -2,6 +2,8 @@ """ Support for POSIX locales. """ +raise ImportError("_locale.py is still incomplete") + from ctypes import (Structure, POINTER, create_string_buffer, c_ubyte, c_int, c_char_p, c_wchar_p) from ctypes_support import standard_c_lib as libc From exarkun at codespeak.net Fri May 9 20:27:45 2008 From: exarkun at codespeak.net (exarkun at codespeak.net) Date: Fri, 9 May 2008 20:27:45 +0200 (CEST) Subject: [pypy-svn] r54608 - pypy/dist/pypy/config Message-ID: <20080509182745.D5E634981EB@codespeak.net> Author: exarkun Date: Fri May 9 20:27:45 2008 New Revision: 54608 Modified: pypy/dist/pypy/config/pypyoption.py Log: Remove _minimal_curses from --allworkingmodules on Windows Translation on Windows is failing with an exception ending with an ImportError for "_curses" from pypy/module/_minimal_curses/interp_curses.py Modified: pypy/dist/pypy/config/pypyoption.py ============================================================================== --- pypy/dist/pypy/config/pypyoption.py (original) +++ pypy/dist/pypy/config/pypyoption.py Fri May 9 20:27:45 2008 @@ -34,7 +34,7 @@ del working_modules["crypt"] del working_modules["termios"] del working_modules["_rawffi"] - + del working_modules["_minimal_curses"] module_dependencies = {} module_suggests = { # the reason you want _rawffi is for ctypes, which From arigo at codespeak.net Fri May 9 23:32:27 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 9 May 2008 23:32:27 +0200 (CEST) Subject: [pypy-svn] r54609 - pypy/dist/pypy/translator/microbench Message-ID: <20080509213227.EF7772A8007@codespeak.net> Author: arigo Date: Fri May 9 23:32:26 2008 New Revision: 54609 Modified: pypy/dist/pypy/translator/microbench/microbench.py Log: Let "-k" match on the tes file name too. Modified: pypy/dist/pypy/translator/microbench/microbench.py ============================================================================== --- pypy/dist/pypy/translator/microbench/microbench.py (original) +++ pypy/dist/pypy/translator/microbench/microbench.py Fri May 9 23:32:26 2008 @@ -38,7 +38,7 @@ for k in [s for s in testmoddict if s.startswith('test_')] : if test_cases: for tc in test_cases: - if k.startswith(tc): + if k.startswith(tc) or microbench.startswith(tc): break else: continue From arigo at codespeak.net Sat May 10 10:20:50 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 10 May 2008 10:20:50 +0200 (CEST) Subject: [pypy-svn] r54611 - in pypy/dist/pypy/rpython: lltypesystem memory memory/gc memory/gc/test memory/gctransform memory/test Message-ID: <20080510082050.A5A922A80B1@codespeak.net> Author: arigo Date: Sat May 10 10:20:48 2008 New Revision: 54611 Added: pypy/dist/pypy/rpython/memory/gc/test/test_direct.py - copied unchanged from r54605, pypy/branch/gc-tweak/pypy/rpython/memory/gc/test/test_direct.py pypy/dist/pypy/rpython/memory/lldict.py - copied unchanged from r54605, pypy/branch/gc-tweak/pypy/rpython/memory/lldict.py pypy/dist/pypy/rpython/memory/test/test_lldict.py - copied unchanged from r54605, pypy/branch/gc-tweak/pypy/rpython/memory/test/test_lldict.py Modified: pypy/dist/pypy/rpython/lltypesystem/llmemory.py pypy/dist/pypy/rpython/lltypesystem/lltype.py pypy/dist/pypy/rpython/lltypesystem/opimpl.py pypy/dist/pypy/rpython/lltypesystem/rdict.py pypy/dist/pypy/rpython/memory/gc/base.py pypy/dist/pypy/rpython/memory/gc/generation.py pypy/dist/pypy/rpython/memory/gc/hybrid.py pypy/dist/pypy/rpython/memory/gc/semispace.py pypy/dist/pypy/rpython/memory/gctransform/framework.py pypy/dist/pypy/rpython/memory/gctypelayout.py pypy/dist/pypy/rpython/memory/gcwrapper.py pypy/dist/pypy/rpython/memory/support.py pypy/dist/pypy/rpython/memory/test/test_gc.py pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py Log: Merge the gc-tweak branch. (svn merge -r54384:54605 svn+ssh://codespeak.net/svn/pypy/branch/gc-tweak) * Build on top of the GenerationGC's GCFLAG_NO_HEAP_PTRS flag to make the HybridGC a full 3-generations collector. This increases the complexity of the HybridGC, but it seems worth the trouble: it seems to remove the few bad cases on tuatara's microbenchmarks where the HybridGC was much slower than the others, and it gives +20% on "pypy-c translate.py --gc=semispace targetgcbench". * Add optional heap consistency checks after each collection. Useful to find GC bugs. * Add a few direct GC tests that can run without the llinterpreter at all (gc/test_direct.py). * Add an AddressDict. Based on lltypesystem/rdict.py but without using the GC itself. * Kill the obscure id() logic, and replace it with something custom but sane in each GC class. Motivated by profiling showing that 26% of L2 cache read misses came from the old id() logic in the above pypy-c translate.py run. Modified: pypy/dist/pypy/rpython/lltypesystem/llmemory.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/llmemory.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/llmemory.py Sat May 10 10:20:48 2008 @@ -582,8 +582,10 @@ def cast_adr_to_int(adr): return adr._cast_to_int() +_NONGCREF = lltype.Ptr(lltype.OpaqueType('NONGCREF')) def cast_int_to_adr(int): - raise NotImplementedError("cast_int_to_adr") + ptr = lltype.cast_int_to_ptr(_NONGCREF, int) + return cast_ptr_to_adr(ptr) # ____________________________________________________________ # Weakrefs. Modified: pypy/dist/pypy/rpython/lltypesystem/lltype.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/lltype.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/lltype.py Sat May 10 10:20:48 2008 @@ -905,6 +905,8 @@ return p # primitive if not p: return None # null pointer + if type(p._obj0) is int: + return p # a pointer obtained by cast_int_to_ptr container = p._obj._normalizedcontainer() if container is not p._obj: p = _ptr(Ptr(typeOf(container)), container, p._solid) @@ -985,7 +987,7 @@ _obj = property(_getobj) def _was_freed(self): - return (self._obj0 is not None and + return (type(self._obj0) not in (type(None), int) and self._getobj(check=False)._was_freed()) def __getattr__(self, field_name): # ! can only return basic or ptr ! Modified: pypy/dist/pypy/rpython/lltypesystem/opimpl.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/opimpl.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/opimpl.py Sat May 10 10:20:48 2008 @@ -383,7 +383,8 @@ def op_debug_print(*args): for arg in args: - print arg + print arg, + print # ____________________________________________________________ Modified: pypy/dist/pypy/rpython/lltypesystem/rdict.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rdict.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rdict.py Sat May 10 10:20:48 2008 @@ -76,6 +76,8 @@ # compute the shape of the DICTENTRY structure entryfields = [] entrymeths = { + 'allocate': lltype.typeMethod(_ll_malloc_entries), + 'delete': _ll_free_entries, 'must_clear_key': (isinstance(self.DICTKEY, lltype.Ptr) and self.DICTKEY._needsgc()), 'must_clear_value': (isinstance(self.DICTVALUE, lltype.Ptr) @@ -189,6 +191,7 @@ } adtmeths['KEY'] = self.DICTKEY adtmeths['VALUE'] = self.DICTVALUE + adtmeths['allocate'] = lltype.typeMethod(_ll_malloc_dict) self.DICT.become(lltype.GcStruct("dicttable", adtmeths=adtmeths, *fields)) @@ -485,7 +488,7 @@ new_size = old_size * 2 while new_size > DICT_INITSIZE and d.num_items < new_size / 4: new_size /= 2 - d.entries = lltype.malloc(lltype.typeOf(old_entries).TO, new_size, zero=True) + d.entries = lltype.typeOf(old_entries).TO.allocate(new_size) d.num_items = 0 d.num_pristine_entries = new_size i = 0 @@ -495,6 +498,7 @@ entry = old_entries[i] ll_dict_insertclean(d, entry.key, entry.value, hash) i += 1 + old_entries.delete() # ------- a port of CPython's dictobject.c's lookdict implementation ------- PERTURB_SHIFT = 5 @@ -582,8 +586,8 @@ DICT_INITSIZE = 8 def ll_newdict(DICT): - d = lltype.malloc(DICT) - d.entries = lltype.malloc(DICT.entries.TO, DICT_INITSIZE, zero=True) + d = DICT.allocate() + d.entries = DICT.entries.TO.allocate(DICT_INITSIZE) d.num_items = 0 d.num_pristine_entries = DICT_INITSIZE return d @@ -594,13 +598,23 @@ n = DICT_INITSIZE while n < length_estimate: n *= 2 - d = lltype.malloc(DICT) - d.entries = lltype.malloc(DICT.entries.TO, n, zero=True) + d = DICT.allocate() + d.entries = DICT.entries.TO.allocate(n) d.num_items = 0 d.num_pristine_entries = n return d ll_newdict_size.oopspec = 'newdict()' +# pypy.rpython.memory.lldict uses a dict based on Struct and Array +# instead of GcStruct and GcArray, which is done by using different +# 'allocate' and 'delete' adtmethod implementations than the ones below +def _ll_malloc_dict(DICT): + return lltype.malloc(DICT) +def _ll_malloc_entries(ENTRIES, n): + return lltype.malloc(ENTRIES, n, zero=True) +def _ll_free_entries(entries): + pass + def rtype_r_dict(hop): r_dict = hop.r_result @@ -691,8 +705,8 @@ def ll_copy(dict): DICT = lltype.typeOf(dict).TO dictsize = len(dict.entries) - d = lltype.malloc(DICT) - d.entries = lltype.malloc(DICT.entries.TO, dictsize, zero=True) + d = DICT.allocate() + d.entries = DICT.entries.TO.allocate(dictsize) d.num_items = dict.num_items d.num_pristine_entries = dict.num_pristine_entries if hasattr(DICT, 'fnkeyeq'): d.fnkeyeq = dict.fnkeyeq @@ -713,10 +727,11 @@ def ll_clear(d): if len(d.entries) == d.num_pristine_entries == DICT_INITSIZE: return - DICT = lltype.typeOf(d).TO - d.entries = lltype.malloc(DICT.entries.TO, DICT_INITSIZE, zero=True) + old_entries = d.entries + d.entries = lltype.typeOf(old_entries).TO.allocate(DICT_INITSIZE) d.num_items = 0 d.num_pristine_entries = DICT_INITSIZE + old_entries.delete() def ll_update(dic1, dic2): entries = dic2.entries Modified: pypy/dist/pypy/rpython/memory/gc/base.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gc/base.py (original) +++ pypy/dist/pypy/rpython/memory/gc/base.py Sat May 10 10:20:48 2008 @@ -8,6 +8,12 @@ malloc_zero_filled = False prebuilt_gc_objects_are_static_roots = True + # The following flag enables costly consistency checks after each + # collection. It is automatically set to True by test_gc.py. The + # checking logic is translatable, so the flag can be set to True + # here before translation. + DEBUG = False + def set_query_functions(self, is_varsize, has_gcptr_in_varsize, is_gcarrayofgcptr, getfinalizer, @@ -148,113 +154,49 @@ length -= 1 trace._annspecialcase_ = 'specialize:arg(2)' + def debug_check_consistency(self): + """To use after a collection. If self.DEBUG is set, this + enumerates all roots and traces all objects to check if we didn't + accidentally free a reachable object or forgot to update a pointer + to an object that moved. + """ + if self.DEBUG: + from pypy.rlib.objectmodel import we_are_translated + from pypy.rpython.memory.support import AddressDict + self._debug_seen = AddressDict() + self._debug_pending = self.AddressStack() + if not we_are_translated(): + self.root_walker._walk_prebuilt_gc(self._debug_record) + callback = GCBase._debug_callback + self.root_walker.walk_roots(callback, callback, callback) + pending = self._debug_pending + while pending.non_empty(): + obj = pending.pop() + self.debug_check_object(obj) + self.trace(obj, self._debug_callback2, None) + self._debug_seen.delete() + self._debug_pending.delete() + + def _debug_record(self, obj): + seen = self._debug_seen + if not seen.contains(obj): + seen.add(obj) + self._debug_pending.append(obj) + def _debug_callback(self, root): + obj = root.address[0] + ll_assert(bool(obj), "NULL address from walk_roots()") + self._debug_record(obj) + def _debug_callback2(self, pointer, ignored): + obj = pointer.address[0] + if obj: + self._debug_record(obj) -class MovingGCBase(GCBase): - moving_gc = True + def debug_check_object(self, obj): + pass - def __init__(self): - # WaRnInG! Putting GC objects as fields of the GC itself is - # basically *not* working in general! When running tests with - # the gcwrapper, there is no way they can be returned from - # get_roots_from_llinterp(). When the whole GC goes through the - # gctransformer, though, it works if the fields are read-only - # (and thus only ever reference a prebuilt list or dict). These - # prebuilt lists or dicts themselves can be mutated and point to - # more non-prebuild GC objects; this is fine because the - # internal GC ptr in the prebuilt list or dict is found by - # gctypelayout and listed in addresses_of_static_ptrs. - - # XXX I'm not sure any more about the warning above. The fields - # of 'self' are found by gctypelayout and added to - # addresses_of_static_ptrs_in_nongc, so in principle they could - # be mutated and still be found by collect(). - - self.wr_to_objects_with_id = [] - self.object_id_dict = {} - self.object_id_dict_ends_at = 0 - def id(self, ptr): - self.disable_finalizers() - try: - return self._compute_id(ptr) - finally: - self.enable_finalizers() - - def _compute_id(self, ptr): - # XXX this may explode if --no-translation-rweakref is specified - # ---------------------------------------------------------------- - # Basic logic: the list item wr_to_objects_with_id[i] contains a - # weakref to the object whose id is i + 1. The object_id_dict is - # an optimization that tries to reduce the number of linear - # searches in this list. - # ---------------------------------------------------------------- - # Invariant: if object_id_dict_ends_at >= 0, then object_id_dict - # contains all pairs {address: id}, for the addresses - # of all objects that are the targets of the weakrefs of the - # following slice: wr_to_objects_with_id[:object_id_dict_ends_at]. - # ---------------------------------------------------------------- - # Essential: as long as notify_objects_just_moved() is not called, - # we assume that the objects' addresses did not change. We also - # assume that the address of a live object cannot be reused for - # another object without an intervening notify_objects_just_moved() - # call, but this could be fixed easily if needed. - # ---------------------------------------------------------------- - # First check the dictionary - i = self.object_id_dict_ends_at - if i < 0: - self.object_id_dict.clear() # dictionary invalid - self.object_id_dict_ends_at = 0 - i = 0 - else: - adr = llmemory.cast_ptr_to_adr(ptr) - try: - i = self.object_id_dict[adr] - except KeyError: - pass - else: - # double-check that the answer we got is correct - lst = self.wr_to_objects_with_id - target = llmemory.weakref_deref(llmemory.GCREF, lst[i]) - ll_assert(target == ptr, "bogus object_id_dict") - return i + 1 # found via the dict - # Walk the tail of the list, where entries are not also in the dict - lst = self.wr_to_objects_with_id - end = len(lst) - freeentry = -1 - while i < end: - target = llmemory.weakref_deref(llmemory.GCREF, lst[i]) - if not target: - freeentry = i - else: - ll_assert(self.get_type_id(llmemory.cast_ptr_to_adr(target)) - > 0, "bogus weakref in compute_id()") - # record this entry in the dict - adr = llmemory.cast_ptr_to_adr(target) - self.object_id_dict[adr] = i - if target == ptr: - break # found - i += 1 - else: - # not found - wr = llmemory.weakref_create(ptr) - if freeentry < 0: - ll_assert(end == len(lst), "unexpected lst growth in gc_id") - i = end - lst.append(wr) - else: - i = freeentry # reuse the id() of a dead object - lst[i] = wr - adr = llmemory.cast_ptr_to_adr(ptr) - self.object_id_dict[adr] = i - # all entries up to and including index 'i' are now valid in the dict - # unless a collection occurred while we were working, in which case - # the object_id_dict is bogus anyway - if self.object_id_dict_ends_at >= 0: - self.object_id_dict_ends_at = i + 1 - return i + 1 # this produces id() values 1, 2, 3, 4... - - def notify_objects_just_moved(self): - self.object_id_dict_ends_at = -1 +class MovingGCBase(GCBase): + moving_gc = True def choose_gc_from_config(config): Modified: pypy/dist/pypy/rpython/memory/gc/generation.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gc/generation.py (original) +++ pypy/dist/pypy/rpython/memory/gc/generation.py Sat May 10 10:20:48 2008 @@ -16,8 +16,12 @@ # pointer to a young object. GCFLAG_NO_YOUNG_PTRS = SemiSpaceGC.first_unused_gcflag << 0 -# The following flag is set for static roots which are not on the list -# of static roots yet, but will appear with write barrier +# The following flag is set on some last-generation objects (== prebuilt +# objects for GenerationGC, but see also HybridGC). The flag is set +# unless the object is already listed in 'last_generation_root_objects'. +# When a pointer is written inside an object with GCFLAG_NO_HEAP_PTRS +# set, the write_barrier clears the flag and adds the object to +# 'last_generation_root_objects'. GCFLAG_NO_HEAP_PTRS = SemiSpaceGC.first_unused_gcflag << 1 class GenerationGC(SemiSpaceGC): @@ -70,6 +74,8 @@ self.lb_young_var_basesize = sz def setup(self): + self.last_generation_root_objects = self.AddressStack() + self.young_objects_with_id = self.AddressDict() SemiSpaceGC.setup(self) self.set_nursery_size(self.initial_nursery_size) # the GC is fully setup now. The rest can make use of it. @@ -244,6 +250,7 @@ def semispace_collect(self, size_changing=False): self.reset_young_gcflags() # we are doing a full collection anyway self.weakrefs_grow_older() + self.ids_grow_older() self.reset_nursery() if DEBUG_PRINT: llop.debug_print(lltype.Void, "major collect, size changing", size_changing) @@ -281,6 +288,42 @@ obj = self.young_objects_with_weakrefs.pop() self.objects_with_weakrefs.append(obj) + def collect_roots(self): + """GenerationGC: collects all roots. + HybridGC: collects all roots, excluding the generation 3 ones. + """ + # Warning! References from static (and possibly gen3) objects + # are found by collect_last_generation_roots(), which must be + # called *first*! If it is called after walk_roots(), then the + # HybridGC explodes if one of the _collect_root causes an object + # to be added to self.last_generation_root_objects. Indeed, in + # this case, the newly added object is traced twice: once by + # collect_last_generation_roots() and once because it was added + # in self.rawmalloced_objects_to_trace. + self.collect_last_generation_roots() + self.root_walker.walk_roots( + SemiSpaceGC._collect_root, # stack roots + SemiSpaceGC._collect_root, # static in prebuilt non-gc structures + None) # we don't need the static in prebuilt gc objects + + def collect_last_generation_roots(self): + stack = self.last_generation_root_objects + self.last_generation_root_objects = self.AddressStack() + while stack.non_empty(): + obj = stack.pop() + self.header(obj).tid |= GCFLAG_NO_HEAP_PTRS + # ^^^ the flag we just added will be removed immediately if + # the object still contains pointers to younger objects + self.trace(obj, self._trace_external_obj, obj) + stack.delete() + + def _trace_external_obj(self, pointer, obj): + addr = pointer.address[0] + if addr != NULL: + newaddr = self.copy(addr) + pointer.address[0] = newaddr + self.write_into_last_generation_obj(obj, newaddr) + # ____________________________________________________________ # Implementation of nursery-only collections @@ -302,11 +345,13 @@ # GCFLAG_NO_YOUNG_PTRS set again by trace_and_drag_out_of_nursery if self.young_objects_with_weakrefs.non_empty(): self.invalidate_young_weakrefs() - self.notify_objects_just_moved() + if self.young_objects_with_id.length() > 0: + self.update_young_objects_with_id() # mark the nursery as free and fill it with zeroes again llarena.arena_reset(self.nursery, self.nursery_size, True) if DEBUG_PRINT: llop.debug_print(lltype.Void, "percent survived:", float(scan - beginning) / self.nursery_size) + #self.debug_check_consistency() # -- quite expensive else: # no nursery - this occurs after a full collect, triggered either # just above or by some previous non-nursery-based allocation. @@ -390,25 +435,106 @@ if self.header(addr_struct).tid & GCFLAG_NO_YOUNG_PTRS: self.remember_young_pointer(addr_struct, newvalue) - def append_to_static_roots(self, pointer, arg): - self.root_walker.append_static_root(pointer) - - def move_to_static_roots(self, addr_struct): - objhdr = self.header(addr_struct) - objhdr.tid &= ~GCFLAG_NO_HEAP_PTRS - self.trace(addr_struct, self.append_to_static_roots, None) - def remember_young_pointer(self, addr_struct, addr): ll_assert(not self.is_in_nursery(addr_struct), "nursery object with GCFLAG_NO_YOUNG_PTRS") - oldhdr = self.header(addr_struct) if self.is_in_nursery(addr): self.old_objects_pointing_to_young.append(addr_struct) - oldhdr.tid &= ~GCFLAG_NO_YOUNG_PTRS - if oldhdr.tid & GCFLAG_NO_HEAP_PTRS: - self.move_to_static_roots(addr_struct) + self.header(addr_struct).tid &= ~GCFLAG_NO_YOUNG_PTRS + elif addr == NULL: + return + self.write_into_last_generation_obj(addr_struct, addr) remember_young_pointer._dont_inline_ = True + def write_into_last_generation_obj(self, addr_struct, addr): + objhdr = self.header(addr_struct) + if objhdr.tid & GCFLAG_NO_HEAP_PTRS: + if not self.is_last_generation(addr): + objhdr.tid &= ~GCFLAG_NO_HEAP_PTRS + self.last_generation_root_objects.append(addr_struct) + + def is_last_generation(self, obj): + # overridden by HybridGC + return (self.header(obj).tid & GCFLAG_EXTERNAL) != 0 + + def _compute_id(self, obj): + if self.is_in_nursery(obj): + result = self.young_objects_with_id.get(obj) + if not result: + result = self._next_id() + self.young_objects_with_id.setitem(obj, result) + return result + else: + return SemiSpaceGC._compute_id(self, obj) + + def update_young_objects_with_id(self): + self.young_objects_with_id.foreach(self._update_object_id, + self.objects_with_id) + self.young_objects_with_id.clear() + # NB. the clear() also makes the dictionary shrink back to its + # minimal size, which is actually a good idea: a large, mostly-empty + # table is bad for the next call to 'foreach'. + + def ids_grow_older(self): + self.young_objects_with_id.foreach(self._id_grow_older, None) + self.young_objects_with_id.clear() + + def _id_grow_older(self, obj, id, ignored): + self.objects_with_id.setitem(obj, id) + + def debug_check_object(self, obj): + """Check the invariants about 'obj' that should be true + between collections.""" + SemiSpaceGC.debug_check_object(self, obj) + tid = self.header(obj).tid + if tid & GCFLAG_NO_YOUNG_PTRS: + ll_assert(not self.is_in_nursery(obj), + "nursery object with GCFLAG_NO_YOUNG_PTRS") + self.trace(obj, self._debug_no_nursery_pointer, None) + elif not self.is_in_nursery(obj): + ll_assert(self._d_oopty.contains(obj), + "missing from old_objects_pointing_to_young") + if tid & GCFLAG_NO_HEAP_PTRS: + ll_assert(self.is_last_generation(obj), + "GCFLAG_NO_HEAP_PTRS on non-3rd-generation object") + self.trace(obj, self._debug_no_gen1or2_pointer, None) + elif self.is_last_generation(obj): + ll_assert(self._d_lgro.contains(obj), + "missing from last_generation_root_objects") + + def _debug_no_nursery_pointer(self, root, ignored): + ll_assert(not self.is_in_nursery(root.address[0]), + "GCFLAG_NO_YOUNG_PTRS but found a young pointer") + def _debug_no_gen1or2_pointer(self, root, ignored): + target = root.address[0] + ll_assert(not target or self.is_last_generation(target), + "GCFLAG_NO_HEAP_PTRS but found a pointer to gen1or2") + + def debug_check_consistency(self): + if self.DEBUG: + self._d_oopty = self.old_objects_pointing_to_young.stack2dict() + self._d_lgro = self.last_generation_root_objects.stack2dict() + SemiSpaceGC.debug_check_consistency(self) + self._d_oopty.delete() + self._d_lgro.delete() + self.old_objects_pointing_to_young.foreach( + self._debug_check_flag_1, None) + self.last_generation_root_objects.foreach( + self._debug_check_flag_2, None) + + def _debug_check_flag_1(self, obj, ignored): + ll_assert(not (self.header(obj).tid & GCFLAG_NO_YOUNG_PTRS), + "unexpected GCFLAG_NO_YOUNG_PTRS") + def _debug_check_flag_2(self, obj, ignored): + ll_assert(not (self.header(obj).tid & GCFLAG_NO_HEAP_PTRS), + "unexpected GCFLAG_NO_HEAP_PTRS") + + def debug_check_can_copy(self, obj): + if self.is_in_nursery(obj): + pass # it's ok to copy an object out of the nursery + else: + SemiSpaceGC.debug_check_can_copy(self, obj) + # ____________________________________________________________ import os Modified: pypy/dist/pypy/rpython/memory/gc/hybrid.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gc/hybrid.py (original) +++ pypy/dist/pypy/rpython/memory/gc/hybrid.py Sat May 10 10:20:48 2008 @@ -2,30 +2,72 @@ from pypy.rpython.memory.gc.semispace import SemiSpaceGC from pypy.rpython.memory.gc.semispace import DEBUG_PRINT from pypy.rpython.memory.gc.generation import GenerationGC, GCFLAG_FORWARDED +from pypy.rpython.memory.gc.semispace import GCFLAG_EXTERNAL from pypy.rpython.memory.gc.generation import GCFLAG_NO_YOUNG_PTRS +from pypy.rpython.memory.gc.generation import GCFLAG_NO_HEAP_PTRS from pypy.rpython.lltypesystem import lltype, llmemory, llarena from pypy.rpython.lltypesystem.llmemory import raw_malloc_usage from pypy.rpython.lltypesystem.lloperation import llop from pypy.rlib.debug import ll_assert from pypy.rlib.rarithmetic import ovfcheck -# The "age" of an object is the number of times it is copied between the -# two semispaces. When an object would reach MAX_SEMISPACE_AGE, it is -# instead copied to a nonmoving location. For example, a value of 4 +# _______in the semispaces_________ ______external (non-moving)_____ +# / \ / \ +# ___raw_malloc'ed__ _prebuilt_ +# +----------------------------------+ / \ / \ +# | | | | | | | | +# | | | | | | | | age < max age == max +# |nur-|o|o|o|o| | | +---+ +---+ +---+ +# |sery|b|b|b|b|free| empty | |obj| |obj| |obj| +# | |j|j|j|j| | | +---+ +---+ +---+ +# | | | | | | | | +---+ +---+ +---+ +# +-----------------+----------------+ |obj| |obj| |obj| +# age <= max +---+ +---+ +---+ +# +# |gen1|------------- generation 2 -----------------|-----generation 3-----| +# +# Object lists: +# * gen2_rawmalloced_objects +# * gen3_rawmalloced_objects +# * old_objects_pointing_to_young: gen2or3 objs that point to gen1 objs +# * last_generation_root_objects: gen3 objs that point to gen1or2 objs +# +# How to tell the objects apart: +# * external: tid & GCFLAG_EXTERNAL +# * gen1: is_in_nursery(obj) +# * gen3: (tid & (GCFLAG_EXTERNAL|GCFLAG_AGE_MASK)) == +# (GCFLAG_EXTERNAL|GCFLAG_AGE_MAX) +# +# Some invariants: +# * gen3 are either GCFLAG_NO_HEAP_PTRS or in 'last_generation_root_objects' +# * between collections, GCFLAG_UNVISITED set exactly for gen2_rawmalloced +# +# A malloc_varsize() of large objects returns objects that are external +# but initially of generation 2. Old objects from the semispaces are +# moved to external objects directly as generation 3. + +# The "age" of an object is the number of times it survived a full +# collections, without counting the step that moved it out of the nursery. +# When a semispace-based object would grow older than MAX_SEMISPACE_AGE, +# it is instead copied to a nonmoving location. For example, a value of 3 # ensures that an object is copied at most 5 times in total: from the # nursery to the semispace, then three times between the two spaces, # then one last time to a nonmoving location. -MAX_SEMISPACE_AGE = 4 +MAX_SEMISPACE_AGE = 3 GCFLAG_UNVISITED = GenerationGC.first_unused_gcflag << 0 _gcflag_next_bit = GenerationGC.first_unused_gcflag << 1 GCFLAG_AGE_ONE = _gcflag_next_bit -GCFLAG_AGE_MAX = _gcflag_next_bit * (MAX_SEMISPACE_AGE-1) +GCFLAG_AGE_MAX = _gcflag_next_bit * MAX_SEMISPACE_AGE GCFLAG_AGE_MASK = 0 while GCFLAG_AGE_MASK < GCFLAG_AGE_MAX: GCFLAG_AGE_MASK |= _gcflag_next_bit _gcflag_next_bit <<= 1 +# The 3rd generation objects are only collected after the following +# number of calls to semispace_collect(): +GENERATION3_COLLECT_THRESHOLD = 20 + class HybridGC(GenerationGC): """A two-generations semi-space GC like the GenerationGC, @@ -33,6 +75,7 @@ they are allocated via raw_malloc/raw_free in a mark-n-sweep fashion. """ first_unused_gcflag = _gcflag_next_bit + prebuilt_gc_objects_are_static_roots = True # the following values override the default arguments of __init__ when # translating to a real backend. @@ -45,6 +88,8 @@ def __init__(self, *args, **kwds): large_object = kwds.pop('large_object', 24) large_object_gcptrs = kwds.pop('large_object_gcptrs', 32) + self.generation3_collect_threshold = kwds.pop( + 'generation3_collect_threshold', GENERATION3_COLLECT_THRESHOLD) GenerationGC.__init__(self, *args, **kwds) # Objects whose total size is at least 'large_object' bytes are @@ -66,10 +111,12 @@ self.large_objects_collect_trigger = self.space_size if DEBUG_PRINT: self._initial_trigger = self.large_objects_collect_trigger - self.pending_external_object_list = self.AddressDeque() + self.rawmalloced_objects_to_trace = self.AddressStack() + self.count_semispaceonly_collects = 0 def setup(self): - self.large_objects_list = self.AddressDeque() + self.gen2_rawmalloced_objects = self.AddressStack() + self.gen3_rawmalloced_objects = self.AddressStack() GenerationGC.setup(self) def set_max_heap_size(self, size): @@ -184,7 +231,7 @@ # need to follow suit. llmemory.raw_memclear(result, totalsize) size_gc_header = self.gcheaderbuilder.size_gc_header - self.large_objects_list.append(result + size_gc_header) + self.gen2_rawmalloced_objects.append(result + size_gc_header) return result def allocate_external_object(self, totalsize): @@ -192,19 +239,62 @@ # If so, we'd also use arena_reset() in malloc_varsize_marknsweep(). return llmemory.raw_malloc(totalsize) + def init_gc_object_immortal(self, addr, typeid, + flags=(GCFLAG_NO_YOUNG_PTRS | + GCFLAG_NO_HEAP_PTRS | + GCFLAG_AGE_MAX)): + GenerationGC.init_gc_object_immortal(self, addr, typeid, flags) + + # ___________________________________________________________________ + # collect() and semispace_collect() are not synonyms in this GC: the + # former is a complete collect, while the latter is only collecting + # the semispaces and not always doing the mark-n-sweep pass over the + # external objects of 3rd generation. + + def collect(self): + self.count_semispaceonly_collects = self.generation3_collect_threshold + GenerationGC.collect(self) + + def is_collecting_gen3(self): + count = self.count_semispaceonly_collects + return count >= self.generation3_collect_threshold + # ___________________________________________________________________ # the following methods are hook into SemiSpaceGC.semispace_collect() def starting_full_collect(self): - # At the start of a collection, all raw_malloc'ed objects should - # have the GCFLAG_UNVISITED bit set. No other object ever has - # this bit set. - ll_assert(not self.pending_external_object_list.non_empty(), - "pending_external_object_list should be empty at start") + # At the start of a collection, the GCFLAG_UNVISITED bit is set + # exactly on the objects in gen2_rawmalloced_objects. Only + # raw_malloc'ed objects can ever have this bit set. + self.count_semispaceonly_collects += 1 + if self.is_collecting_gen3(): + # set the GCFLAG_UNVISITED on all rawmalloced generation-3 objects + # as well, to let them be recorded by visit_external_object() + self.gen3_rawmalloced_objects.foreach(self._set_gcflag_unvisited, + None) + ll_assert(not self.rawmalloced_objects_to_trace.non_empty(), + "rawmalloced_objects_to_trace should be empty at start") if DEBUG_PRINT: self._nonmoving_copy_count = 0 self._nonmoving_copy_size = 0 + def _set_gcflag_unvisited(self, obj, ignored): + ll_assert(not (self.header(obj).tid & GCFLAG_UNVISITED), + "bogus GCFLAG_UNVISITED on gen3 obj") + self.header(obj).tid |= GCFLAG_UNVISITED + + def collect_roots(self): + if not self.is_collecting_gen3(): + GenerationGC.collect_roots(self) + else: + # as we don't record which prebuilt gc objects point to + # rawmalloced generation 3 objects, we have to trace all + # the prebuilt gc objects. + self.root_walker.walk_roots( + SemiSpaceGC._collect_root, # stack roots + SemiSpaceGC._collect_root, # static in prebuilt non-gc structs + SemiSpaceGC._collect_root) # static in prebuilt gc objects + def surviving(self, obj): # To use during a collection. The objects that survive are the # ones with GCFLAG_FORWARDED set and GCFLAG_UNVISITED not set. @@ -213,12 +303,16 @@ flags = self.header(obj).tid & (GCFLAG_FORWARDED|GCFLAG_UNVISITED) return flags == GCFLAG_FORWARDED + def is_last_generation(self, obj): + return ((self.header(obj).tid & (GCFLAG_EXTERNAL|GCFLAG_AGE_MASK)) == + (GCFLAG_EXTERNAL|GCFLAG_AGE_MAX)) + def visit_external_object(self, obj): hdr = self.header(obj) if hdr.tid & GCFLAG_UNVISITED: # This is a not-visited-yet raw_malloced object. hdr.tid -= GCFLAG_UNVISITED - self.pending_external_object_list.append(obj) + self.rawmalloced_objects_to_trace.append(obj) def make_a_copy(self, obj, objsize): # During a full collect, all copied objects might implicitly come @@ -246,20 +340,26 @@ # NB. the object can have a finalizer or be a weakref, but # it's not an issue. totalsize = self.size_gc_header() + objsize - if DEBUG_PRINT: - self._nonmoving_copy_count += 1 - self._nonmoving_copy_size += raw_malloc_usage(totalsize) newaddr = self.allocate_external_object(totalsize) if not newaddr: return llmemory.NULL # can't raise MemoryError during a collect() + if DEBUG_PRINT: + self._nonmoving_copy_count += 1 + self._nonmoving_copy_size += raw_malloc_usage(totalsize) llmemory.raw_memcopy(obj - self.size_gc_header(), newaddr, totalsize) newobj = newaddr + self.size_gc_header() hdr = self.header(newobj) hdr.tid |= self.GCFLAGS_FOR_NEW_EXTERNAL_OBJECTS # GCFLAG_UNVISITED is not set - self.large_objects_list.append(newobj) - self.pending_external_object_list.append(newobj) + # GCFLAG_NO_HEAP_PTRS is not set either, conservatively. It may be + # set by the next collection's collect_last_generation_roots(). + # This old object is immediately put at generation 3. + ll_assert(self.is_last_generation(newobj), + "make_a_nonmoving_copy: object too young") + self.gen3_rawmalloced_objects.append(newobj) + self.last_generation_root_objects.append(newobj) + self.rawmalloced_objects_to_trace.append(newobj) # visit me return newobj def scan_copied(self, scan): @@ -270,23 +370,62 @@ newscan = GenerationGC.scan_copied(self, scan) progress = newscan != scan scan = newscan - while self.pending_external_object_list.non_empty(): - obj = self.pending_external_object_list.popleft() + while self.rawmalloced_objects_to_trace.non_empty(): + obj = self.rawmalloced_objects_to_trace.pop() self.trace_and_copy(obj) progress = True return scan def finished_full_collect(self): - ll_assert(not self.pending_external_object_list.non_empty(), - "pending_external_object_list should be empty at end") - # free all mark-n-sweep-managed objects that have not been marked - large_objects = self.large_objects_list - remaining_large_objects = self.AddressDeque() + ll_assert(not self.rawmalloced_objects_to_trace.non_empty(), + "rawmalloced_objects_to_trace should be empty at end") + if DEBUG_PRINT: + llop.debug_print(lltype.Void, + "| [hybrid] made nonmoving: ", + self._nonmoving_copy_size, "bytes in", + self._nonmoving_copy_count, "objs") + # sweep the nonmarked rawmalloced objects + if self.is_collecting_gen3(): + self.sweep_rawmalloced_objects(generation=3) + self.sweep_rawmalloced_objects(generation=2) + # As we just collected, it's fine to raw_malloc'ate up to space_size + # bytes again before we should force another collect. + self.large_objects_collect_trigger = self.space_size + if self.is_collecting_gen3(): + self.count_semispaceonly_collects = 0 + if DEBUG_PRINT: + self._initial_trigger = self.large_objects_collect_trigger + + def sweep_rawmalloced_objects(self, generation): + # free all the rawmalloced objects of the specified generation + # that have not been marked + if generation == 2: + objects = self.gen2_rawmalloced_objects + # generation 2 sweep: if A points to an object object B that + # moves from gen2 to gen3, it's possible that A no longer points + # to any gen2 object. In this case, A remains a bit too long in + # last_generation_root_objects, but this will be fixed by the + # next collect_last_generation_roots(). + else: + objects = self.gen3_rawmalloced_objects + # generation 3 sweep: remove from last_generation_root_objects + # all the objects that we are about to free + gen3roots = self.last_generation_root_objects + newgen3roots = self.AddressStack() + while gen3roots.non_empty(): + obj = gen3roots.pop() + if not (self.header(obj).tid & GCFLAG_UNVISITED): + newgen3roots.append(obj) + gen3roots.delete() + self.last_generation_root_objects = newgen3roots + + surviving_objects = self.AddressStack() if DEBUG_PRINT: alive_count = alive_size = 0 if DEBUG_PRINT: dead_count = dead_size = 0 - while large_objects.non_empty(): - obj = large_objects.popleft() - if self.header(obj).tid & GCFLAG_UNVISITED: + while objects.non_empty(): + obj = objects.pop() + tid = self.header(obj).tid + if tid & GCFLAG_UNVISITED: if DEBUG_PRINT:dead_count+=1 if DEBUG_PRINT:dead_size+=raw_malloc_usage(self.get_size(obj)) addr = obj - self.gcheaderbuilder.size_gc_header @@ -294,25 +433,85 @@ else: if DEBUG_PRINT:alive_count+=1 if DEBUG_PRINT:alive_size+=raw_malloc_usage(self.get_size(obj)) - self.header(obj).tid |= GCFLAG_UNVISITED - remaining_large_objects.append(obj) - large_objects.delete() - self.large_objects_list = remaining_large_objects - # As we just collected, it's fine to raw_malloc'ate up to space_size - # bytes again before we should force another collect. - self.large_objects_collect_trigger = self.space_size - + if generation == 3: + surviving_objects.append(obj) + else: + ll_assert((tid & GCFLAG_AGE_MASK) < GCFLAG_AGE_MAX, + "wrong age for generation 2 object") + tid += GCFLAG_AGE_ONE + if (tid & GCFLAG_AGE_MASK) == GCFLAG_AGE_MAX: + # the object becomes part of generation 3 + self.gen3_rawmalloced_objects.append(obj) + # GCFLAG_NO_HEAP_PTRS not set yet, conservatively + self.last_generation_root_objects.append(obj) + else: + # the object stays in generation 2 + tid |= GCFLAG_UNVISITED + surviving_objects.append(obj) + self.header(obj).tid = tid + objects.delete() + if generation == 2: + self.gen2_rawmalloced_objects = surviving_objects + else: + self.gen3_rawmalloced_objects = surviving_objects if DEBUG_PRINT: - self._initial_trigger = self.large_objects_collect_trigger llop.debug_print(lltype.Void, - "| [hybrid] made nonmoving: ", - self._nonmoving_copy_size, "bytes in", - self._nonmoving_copy_count, "objs") - llop.debug_print(lltype.Void, - "| [hybrid] nonmoving now alive: ", + "| [hyb] gen", generation, + "nonmoving now alive: ", alive_size, "bytes in", alive_count, "objs") llop.debug_print(lltype.Void, - "| [hybrid] nonmoving freed: ", + "| [hyb] gen", generation, + "nonmoving freed: ", dead_size, "bytes in", dead_count, "objs") + + def _compute_id_for_external(self, obj): + # the base classes make the assumption that all external objects + # have an id equal to their address. This is wrong if the object + # is a generation 3 rawmalloced object that initially lived in + # the semispaces. + if self.is_last_generation(obj): + # in this case, we still need to check if the object had its + # id taken before. If not, we can use its address as its id. + return self.objects_with_id.get(obj, obj) + else: + # a generation 2 external object was never non-external in + # the past, so it cannot be listed in self.objects_with_id. + return obj + # XXX a possible optimization would be to use three dicts, one + # for each generation, instead of mixing gen2 and gen3 objects. + + def debug_check_object(self, obj): + """Check the invariants about 'obj' that should be true + between collections.""" + GenerationGC.debug_check_object(self, obj) + tid = self.header(obj).tid + if tid & GCFLAG_UNVISITED: + ll_assert(self._d_gen2ro.contains(obj), + "GCFLAG_UNVISITED on non-gen2 object") + + def debug_check_consistency(self): + if self.DEBUG: + self._d_gen2ro = self.gen2_rawmalloced_objects.stack2dict() + GenerationGC.debug_check_consistency(self) + self._d_gen2ro.delete() + self.gen2_rawmalloced_objects.foreach(self._debug_check_gen2, None) + self.gen3_rawmalloced_objects.foreach(self._debug_check_gen3, None) + + def _debug_check_gen2(self, obj, ignored): + tid = self.header(obj).tid + ll_assert(bool(tid & GCFLAG_EXTERNAL), + "gen2: missing GCFLAG_EXTERNAL") + ll_assert(bool(tid & GCFLAG_UNVISITED), + "gen2: missing GCFLAG_UNVISITED") + ll_assert((tid & GCFLAG_AGE_MASK) < GCFLAG_AGE_MAX, + "gen2: age field too large") + def _debug_check_gen3(self, obj, ignored): + tid = self.header(obj).tid + ll_assert(bool(tid & GCFLAG_EXTERNAL), + "gen3: missing GCFLAG_EXTERNAL") + ll_assert(not (tid & GCFLAG_UNVISITED), + "gen3: unexpected GCFLAG_UNVISITED") + ll_assert((tid & GCFLAG_AGE_MASK) == GCFLAG_AGE_MAX, + "gen3: wrong age field") Modified: pypy/dist/pypy/rpython/memory/gc/semispace.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gc/semispace.py (original) +++ pypy/dist/pypy/rpython/memory/gc/semispace.py Sat May 10 10:20:48 2008 @@ -3,6 +3,7 @@ from pypy.rpython.lltypesystem.llmemory import NULL, raw_malloc_usage from pypy.rpython.memory.support import DEFAULT_CHUNK_SIZE from pypy.rpython.memory.support import get_address_stack, get_address_deque +from pypy.rpython.memory.support import AddressDict from pypy.rpython.memory.gcheader import GCHeaderBuilder from pypy.rpython.lltypesystem import lltype, llmemory, llarena from pypy.rlib.objectmodel import free_non_gc_object @@ -50,8 +51,11 @@ self.gcheaderbuilder = GCHeaderBuilder(self.HDR) self.AddressStack = get_address_stack(chunk_size) self.AddressDeque = get_address_deque(chunk_size) + self.AddressDict = AddressDict self.finalizer_lock_count = 0 self.red_zone = 0 + self.id_free_list = self.AddressStack() + self.next_free_id = 1 def setup(self): if DEBUG_PRINT: @@ -66,6 +70,7 @@ self.objects_with_finalizers = self.AddressDeque() self.run_finalizers = self.AddressDeque() self.objects_with_weakrefs = self.AddressStack() + self.objects_with_id = self.AddressDict() def disable_finalizers(self): self.finalizer_lock_count += 1 @@ -202,9 +207,11 @@ self.max_space_size = size def collect(self): + self.debug_check_consistency() self.semispace_collect() # the indirection is required by the fact that collect() is referred # to by the gc transformer, and the default argument would crash + # (this is also a hook for the HybridGC) def semispace_collect(self, size_changing=False): if DEBUG_PRINT: @@ -233,8 +240,9 @@ scan = self.deal_with_objects_with_finalizers(scan) if self.objects_with_weakrefs.non_empty(): self.invalidate_weakrefs() + self.update_objects_with_id() self.finished_full_collect() - self.notify_objects_just_moved() + self.debug_check_consistency() if not size_changing: llarena.arena_reset(fromspace, self.space_size, True) self.record_red_zone() @@ -314,6 +322,8 @@ root.address[0] = self.copy(root.address[0]) def copy(self, obj): + if self.DEBUG: + self.debug_check_can_copy(obj) if self.is_forwarded(obj): #llop.debug_print(lltype.Void, obj, "already copied to", self.get_forwarding_address(obj)) return self.get_forwarding_address(obj) @@ -568,5 +578,80 @@ finally: self.finalizer_lock_count -= 1 + def id(self, ptr): + obj = llmemory.cast_ptr_to_adr(ptr) + if self.header(obj).tid & GCFLAG_EXTERNAL: + result = self._compute_id_for_external(obj) + else: + result = self._compute_id(obj) + return llmemory.cast_adr_to_int(result) + + def _next_id(self): + # return an id not currently in use (as an address instead of an int) + if self.id_free_list.non_empty(): + result = self.id_free_list.pop() # reuse a dead id + else: + # make up a fresh id number + result = llmemory.cast_int_to_adr(self.next_free_id) + self.next_free_id += 2 # only odd numbers, to make lltype + # and llmemory happy and to avoid + # clashes with real addresses + return result + + def _compute_id(self, obj): + # look if the object is listed in objects_with_id + result = self.objects_with_id.get(obj) + if not result: + result = self._next_id() + self.objects_with_id.setitem(obj, result) + return result + + def _compute_id_for_external(self, obj): + # For prebuilt objects, we can simply return their address. + # This method is overriden by the HybridGC. + return obj + + def update_objects_with_id(self): + old = self.objects_with_id + new_objects_with_id = self.AddressDict(old.length()) + old.foreach(self._update_object_id_FAST, new_objects_with_id) + old.delete() + self.objects_with_id = new_objects_with_id + + def _update_object_id(self, obj, id, new_objects_with_id): + # safe version (used by subclasses) + if self.surviving(obj): + newobj = self.get_forwarding_address(obj) + new_objects_with_id.setitem(newobj, id) + else: + self.id_free_list.append(id) + + def _update_object_id_FAST(self, obj, id, new_objects_with_id): + # unsafe version, assumes that the new_objects_with_id is large enough + if self.surviving(obj): + newobj = self.get_forwarding_address(obj) + new_objects_with_id.insertclean(newobj, id) + else: + self.id_free_list.append(id) + + def debug_check_object(self, obj): + """Check the invariants about 'obj' that should be true + between collections.""" + tid = self.header(obj).tid + if tid & GCFLAG_EXTERNAL: + ll_assert(tid & GCFLAG_FORWARDED, "bug: external+!forwarded") + ll_assert(not (self.tospace <= obj < self.free), + "external flag but object inside the semispaces") + else: + ll_assert(not (tid & GCFLAG_FORWARDED), "bug: !external+forwarded") + ll_assert(self.tospace <= obj < self.free, + "!external flag but object outside the semispaces") + ll_assert(not (tid & GCFLAG_FINALIZATION_ORDERING), + "unexpected GCFLAG_FINALIZATION_ORDERING") + + def debug_check_can_copy(self, obj): + ll_assert(not (self.tospace <= obj < self.free), + "copy() on already-copied object") + STATISTICS_NUMBERS = 0 Modified: pypy/dist/pypy/rpython/memory/gctransform/framework.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gctransform/framework.py (original) +++ pypy/dist/pypy/rpython/memory/gctransform/framework.py Sat May 10 10:20:48 2008 @@ -391,11 +391,8 @@ self.layoutbuilder.addresses_of_static_ptrs_in_nongc + self.layoutbuilder.addresses_of_static_ptrs) log.info("found %s static roots" % (len(addresses_of_static_ptrs), )) - additional_ptrs = self.layoutbuilder.additional_roots_sources - log.info("additional %d potential static roots" % additional_ptrs) ll_static_roots_inside = lltype.malloc(lltype.Array(llmemory.Address), - len(addresses_of_static_ptrs) + - additional_ptrs, + len(addresses_of_static_ptrs), immortal=True) for i in range(len(addresses_of_static_ptrs)): ll_static_roots_inside[i] = addresses_of_static_ptrs[i] @@ -788,10 +785,6 @@ def setup_root_walker(self): pass - def append_static_root(self, adr): - self.gcdata.static_root_end.address[0] = adr - self.gcdata.static_root_end += sizeofaddr - def walk_roots(self, collect_stack_root, collect_static_in_prebuilt_nongc, collect_static_in_prebuilt_gc): Modified: pypy/dist/pypy/rpython/memory/gctypelayout.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gctypelayout.py (original) +++ pypy/dist/pypy/rpython/memory/gctypelayout.py Sat May 10 10:20:48 2008 @@ -193,10 +193,9 @@ self.addresses_of_static_ptrs = [] # this lists contains pointers in raw Structs and Arrays self.addresses_of_static_ptrs_in_nongc = [] - # if not gc.prebuilt_gc_objects_are_static_roots, then - # additional_roots_sources counts the number of locations - # within prebuilt GC objects that are of type Ptr(Gc) - self.additional_roots_sources = 0 + # for debugging, the following list collects all the prebuilt + # GcStructs and GcArrays + self.all_prebuilt_gc = [] self.finalizer_funcptrs = {} self.offsettable_cache = {} self.next_typeid_cache = {} @@ -284,6 +283,7 @@ hdr = gc.gcheaderbuilder.new_header(value) adr = llmemory.cast_ptr_to_adr(hdr) gc.init_gc_object_immortal(adr, typeid) + self.all_prebuilt_gc.append(value) # The following collects the addresses of all the fields that have # a GC Pointer type, inside the current prebuilt object. All such @@ -291,12 +291,10 @@ # they could be changed later to point to GC heap objects. adr = llmemory.cast_ptr_to_adr(value._as_ptr()) if TYPE._gckind == "gc": - if not gc.prebuilt_gc_objects_are_static_roots: - for a in gc_pointers_inside(value, adr): - self.additional_roots_sources += 1 - return - else: + if gc.prebuilt_gc_objects_are_static_roots or gc.DEBUG: appendto = self.addresses_of_static_ptrs + else: + return else: appendto = self.addresses_of_static_ptrs_in_nongc for a in gc_pointers_inside(value, adr, mutable_only=True): Modified: pypy/dist/pypy/rpython/memory/gcwrapper.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gcwrapper.py (original) +++ pypy/dist/pypy/rpython/memory/gcwrapper.py Sat May 10 10:20:48 2008 @@ -10,6 +10,7 @@ def __init__(self, llinterp, flowgraphs, gc_class, GC_PARAMS={}): self.gc = gc_class(chunk_size = 10, **GC_PARAMS) self.gc.set_root_walker(LLInterpRootWalker(self)) + self.gc.DEBUG = True self.llinterp = llinterp self.prepare_graphs(flowgraphs) self.gc.setup() @@ -24,8 +25,9 @@ TYPE = lltype.typeOf(obj) layoutbuilder.consider_constant(TYPE, obj, self.gc) - self.constantroots = list(layoutbuilder.addresses_of_static_ptrs) + self.constantroots = layoutbuilder.addresses_of_static_ptrs self.constantrootsnongc = layoutbuilder.addresses_of_static_ptrs_in_nongc + self._all_prebuilt_gc = layoutbuilder.all_prebuilt_gc # ____________________________________________________________ # @@ -114,9 +116,6 @@ def __init__(self, gcheap): self.gcheap = gcheap - def append_static_root(self, pointer): - self.gcheap.constantroots.append(pointer) - def walk_roots(self, collect_stack_root, collect_static_in_prebuilt_nongc, collect_static_in_prebuilt_gc): @@ -135,6 +134,10 @@ if addrofaddr.address[0]: collect_stack_root(gc, addrofaddr) + def _walk_prebuilt_gc(self, collect): # debugging only! not RPython + for obj in self.gcheap._all_prebuilt_gc: + collect(llmemory.cast_ptr_to_adr(obj._as_ptr())) + class DirectRunLayoutBuilder(gctypelayout.TypeLayoutBuilder): Modified: pypy/dist/pypy/rpython/memory/support.py ============================================================================== --- pypy/dist/pypy/rpython/memory/support.py (original) +++ pypy/dist/pypy/rpython/memory/support.py Sat May 10 10:20:48 2008 @@ -1,5 +1,6 @@ from pypy.rpython.lltypesystem import lltype, llmemory from pypy.rlib.objectmodel import free_non_gc_object, we_are_translated +from pypy.rlib.rarithmetic import r_uint, LONG_BIT from pypy.rlib.debug import ll_assert DEFAULT_CHUNK_SIZE = 1019 @@ -110,6 +111,14 @@ cur = next free_non_gc_object(self) + def length(self): + chunk = self.chunk + count = self.used_in_last_chunk + while chunk: + chunk = chunk.next + count += chunk_size + return count + def foreach(self, callback, arg): """Invoke 'callback(address, arg)' for all addresses in the stack. Typically, 'callback' is a bound method and 'arg' can be None. @@ -124,9 +133,17 @@ count = chunk_size foreach._annspecialcase_ = 'specialize:arg(1)' + def stack2dict(self): + result = AddressDict(self.length()) + self.foreach(_add_in_dict, result) + return result + cache[chunk_size] = AddressStack return AddressStack +def _add_in_dict(item, d): + d.add(item) + def get_address_deque(chunk_size=DEFAULT_CHUNK_SIZE, cache={}): try: @@ -193,3 +210,82 @@ cache[chunk_size] = AddressDeque return AddressDeque + +# ____________________________________________________________ + +def AddressDict(length_estimate=0): + if we_are_translated(): + from pypy.rpython.memory import lldict + return lldict.newdict(length_estimate) + else: + return BasicAddressDict() + +class BasicAddressDict(object): + + def __init__(self): + self.data = {} + + def _key(self, addr): + "NOT_RPYTHON: prebuilt AddressDicts are not supported" + return addr._fixup().ptr._obj + + def _wrapkey(self, obj): + return llmemory.cast_ptr_to_adr(obj._as_ptr()) + + def delete(self): + pass + + def length(self): + return len(self.data) + + def contains(self, keyaddr): + return self._key(keyaddr) in self.data + + def get(self, keyaddr, default=llmemory.NULL): + return self.data.get(self._key(keyaddr), default) + + def setitem(self, keyaddr, valueaddr): + assert keyaddr + self.data[self._key(keyaddr)] = valueaddr + + def insertclean(self, keyaddr, valueaddr): + assert keyaddr + key = self._key(keyaddr) + assert key not in self.data + self.data[key] = valueaddr + + def add(self, keyaddr): + self.setitem(keyaddr, llmemory.NULL) + + def clear(self): + self.data.clear() + + def foreach(self, callback, arg): + """Invoke 'callback(key, value, arg)' for all items in the dict. + Typically, 'callback' is a bound method and 'arg' can be None.""" + for key, value in self.data.iteritems(): + callback(self._wrapkey(key), value, arg) + + +def copy_and_update(dict, surviving, updated_address): + """Make a copy of 'dict' in which the keys are updated as follows: + * if surviving(key) returns False, the item is removed + * otherwise, updated_address(key) is inserted in the copy. + """ + newdict = AddressDict + if not we_are_translated(): + # when not translated, return a dict of the same kind as 'dict' + if not isinstance(dict, BasicAddressDict): + from pypy.rpython.memory.lldict import newdict + result = newdict(dict.length()) + dict.foreach(_get_updater(surviving, updated_address), result) + return result +copy_and_update._annspecialcase_ = 'specialize:arg(1,2)' + +def _get_updater(surviving, updated_address): + def callback(key, value, arg): + if surviving(key): + newkey = updated_address(key) + arg.setitem(newkey, value) + return callback +_get_updater._annspecialcase_ = 'specialize:memo' Modified: pypy/dist/pypy/rpython/memory/test/test_gc.py ============================================================================== --- pypy/dist/pypy/rpython/memory/test/test_gc.py (original) +++ pypy/dist/pypy/rpython/memory/test/test_gc.py Sat May 10 10:20:48 2008 @@ -478,3 +478,46 @@ return b.num_deleted res = self.interpret(f, [15]) assert res == 16 + +class TestHybridGCSmallHeap(GCTest): + from pypy.rpython.memory.gc.hybrid import HybridGC as GCClass + GC_PARAMS = {'space_size': 192, + 'min_nursery_size': 48, + 'nursery_size': 48, + 'large_object': 12, + 'large_object_gcptrs': 12, + 'generation3_collect_threshold': 5, + } + + def test_gen3_to_gen2_refs(self): + class A(object): + def __init__(self): + self.x1 = -1 + def f(x): + loop = A() + loop.next = loop + loop.prev = loop + i = 0 + while i < x: + i += 1 + a1 = A() + a1.x1 = i + a2 = A() + a2.x1 = i + 1000 + a1.prev = loop.prev + a1.prev.next = a1 + a1.next = loop + loop.prev = a1 + a2.prev = loop + a2.next = loop.next + a2.next.prev = a2 + loop.next = a2 + i = 0 + a = loop + while True: + a = a.next + i += 1 + if a is loop: + return i + res = self.interpret(f, [200]) + assert res == 401 Modified: pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py ============================================================================== --- pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py (original) +++ pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py Sat May 10 10:20:48 2008 @@ -855,9 +855,11 @@ run, transformer = self.runner(f, nbargs=2, transformer=True) run([1, 4]) - assert len(transformer.layoutbuilder.addresses_of_static_ptrs) == 0 - assert transformer.layoutbuilder.additional_roots_sources >= 4 - # NB. Remember that additional_roots_sources does not count + if not transformer.GCClass.prebuilt_gc_objects_are_static_roots: + assert len(transformer.layoutbuilder.addresses_of_static_ptrs) == 0 + else: + assert len(transformer.layoutbuilder.addresses_of_static_ptrs) >= 4 + # NB. Remember that the number above does not count # the number of prebuilt GC objects, but the number of locations # within prebuilt GC objects that are of type Ptr(Gc). # At the moment we get additional_roots_sources == 6: @@ -917,3 +919,25 @@ 'nursery_size': 128, 'large_object': 32} root_stack_depth = 200 + + def test_ref_from_rawmalloced_to_regular(self): + import gc + S = lltype.GcStruct('S', ('x', lltype.Signed)) + A = lltype.GcStruct('A', ('p', lltype.Ptr(S)), + ('a', lltype.Array(lltype.Char))) + def setup(j): + p = lltype.malloc(S) + p.x = j*2 + lst = lltype.malloc(A, j) + # the following line generates a write_barrier call at the moment, + # which is important because the 'lst' can be allocated directly + # in generation 2. This can only occur with varsized mallocs. + lst.p = p + return lst + def f(i, j): + lst = setup(j) + gc.collect() + return lst.p.x + run = self.runner(f, nbargs=2) + res = run([100, 100]) + assert res == 200 From arigo at codespeak.net Sat May 10 10:21:36 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 10 May 2008 10:21:36 +0200 (CEST) Subject: [pypy-svn] r54612 - pypy/branch/gc-tweak Message-ID: <20080510082136.4DD452A80B1@codespeak.net> Author: arigo Date: Sat May 10 10:21:35 2008 New Revision: 54612 Removed: pypy/branch/gc-tweak/ Log: Remove merged branch. From fijal at codespeak.net Sat May 10 12:00:24 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 10 May 2008 12:00:24 +0200 (CEST) Subject: [pypy-svn] r54613 - pypy/branch/io-improvements/pypy/rlib Message-ID: <20080510100024.3733749823A@codespeak.net> Author: fijal Date: Sat May 10 12:00:21 2008 New Revision: 54613 Modified: pypy/branch/io-improvements/pypy/rlib/streamio.py Log: This version seems to be slightly faster (but more complex). Feel free to revert. Modified: pypy/branch/io-improvements/pypy/rlib/streamio.py ============================================================================== --- pypy/branch/io-improvements/pypy/rlib/streamio.py (original) +++ pypy/branch/io-improvements/pypy/rlib/streamio.py Sat May 10 12:00:21 2008 @@ -613,29 +613,29 @@ more[-1] = data[:cutoff] return "".join(more) - def _read_next_bunch(self): - self.lines = self.buf.split("\n") - self.buf = self.lines.pop() - self.lines.reverse() - - # slightly more optimized version, because of indirection actually slower + # read_next_bunch is generally this, version below is slightly faster #def _read_next_bunch(self): - # numlines = self.buf.count("\n") - # self.lines = [None] * numlines - # last = -1 - # num = numlines - 1 - # while True: - # start = last + 1 - # assert start >= 0 - # next = self.buf.find("\n", start) - # if next == -1: - # if last != -1: - # self.buf = self.buf[start:] - # break - # assert next >= 0 - # self.lines[num] = self.buf[start:next] - # last = next - # num -= 1 + # self.lines = self.buf.split("\n") + # self.buf = self.lines.pop() + # self.lines.reverse() + + def _read_next_bunch(self): + numlines = self.buf.count("\n") + self.lines = [None] * numlines + last = -1 + num = numlines - 1 + while True: + start = last + 1 + assert start >= 0 + next = self.buf.find("\n", start) + if next == -1: + if last != -1: + self.buf = self.buf[start:] + break + assert next >= 0 + self.lines[num] = self.buf[start:next] + last = next + num -= 1 def readline(self): if self.lines: From antocuni at codespeak.net Sat May 10 12:33:53 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Sat, 10 May 2008 12:33:53 +0200 (CEST) Subject: [pypy-svn] r54614 - pypy/extradoc/sprintinfo/berlin-2008 Message-ID: <20080510103353.9918B49823B@codespeak.net> Author: antocuni Date: Sat May 10 12:33:53 2008 New Revision: 54614 Modified: pypy/extradoc/sprintinfo/berlin-2008/people.txt Log: my dates; I booked the return flight on the 24th by mistake; if anyone is planning to stay one or two days more, please let me know Modified: pypy/extradoc/sprintinfo/berlin-2008/people.txt ============================================================================== --- pypy/extradoc/sprintinfo/berlin-2008/people.txt (original) +++ pypy/extradoc/sprintinfo/berlin-2008/people.txt Sat May 10 12:33:53 2008 @@ -17,6 +17,7 @@ Samuele Pedroni 16-21 Hotel Klassik Berlin Armin Rigo 14-22(noon) private, thanks Stephan Carl Friedrich Bolz 14-22 Die Fabrik +Antonio Cuni 19-24 ? ==================== ============== ======================= People on the following list were present at previous sprints: @@ -52,7 +53,6 @@ Alexandre Fayolle ? ? Sylvain Th?nault ? ? Armin Rigo ? ? -Antonio Cuni ? ? Toby Watson ? ? Paul deGrandis ? ? ==================== ============== ===================== From arigo at codespeak.net Sat May 10 12:43:58 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 10 May 2008 12:43:58 +0200 (CEST) Subject: [pypy-svn] r54615 - in pypy/branch/io-improvements/pypy/rpython/lltypesystem: . test Message-ID: <20080510104358.ACBB2498237@codespeak.net> Author: arigo Date: Sat May 10 12:43:56 2008 New Revision: 54615 Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/llmemory.py pypy/branch/io-improvements/pypy/rpython/lltypesystem/lltype.py pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_llmemory.py pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_lltype.py Log: Test and fix for _subarray not keeping their array alive, which is wrong for raw-malloced objects. Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/llmemory.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/lltypesystem/llmemory.py (original) +++ pypy/branch/io-improvements/pypy/rpython/lltypesystem/llmemory.py Sat May 10 12:43:56 2008 @@ -224,6 +224,7 @@ assert array_type_match(lltype.typeOf(arrayptr).TO, self.TYPE) if isinstance(self.TYPE.OF, lltype.ContainerType): # XXX this doesn't support empty arrays + # XXX it's also missing 'solid' support, probably o = arrayptr._obj.getitem(0) return o._as_ptr() else: Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/lltype.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/lltypesystem/lltype.py (original) +++ pypy/branch/io-improvements/pypy/rpython/lltypesystem/lltype.py Sat May 10 12:43:56 2008 @@ -1512,6 +1512,11 @@ def __init__(self, TYPE, parent, baseoffset_or_fieldname): _parentable.__init__(self, TYPE) self._setparentstructure(parent, baseoffset_or_fieldname) + # Keep the parent array alive, we share the same allocation. + # Don't do it if we are inside a GC object, though -- it's someone + # else's job to keep the GC object alive + if typeOf(top_container(parent))._gckind == 'raw': + self._keepparent = parent def __repr__(self): parent = self._wrparent() Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_llmemory.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_llmemory.py (original) +++ pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_llmemory.py Sat May 10 12:43:56 2008 @@ -589,4 +589,13 @@ a = lltype.malloc(A, flavor='raw') src = cast_ptr_to_adr(a) + itemoffsetof(A, 0) raw_memclear(src, sizeof(lltype.Signed) * 0) - + +def test_addr_keeps_object_alive(): + A = lltype.Array(Address) + ptr = lltype.malloc(A, 10, immortal=True) + adr = cast_ptr_to_adr(ptr) + ArrayItemsOffset(A) + del ptr + import gc; gc.collect(); gc.collect() + # the following line crashes if the array is dead + ptr1 = cast_adr_to_ptr(adr, lltype.Ptr(lltype.FixedSizeArray(Address, 1))) + ptr1[0] = NULL Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_lltype.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_lltype.py (original) +++ pypy/branch/io-improvements/pypy/rpython/lltypesystem/test/test_lltype.py Sat May 10 12:43:56 2008 @@ -727,3 +727,11 @@ setattr(s, word, i) for i, word in enumerate(words): assert getattr(s, word) == i + +def test_subarray_keeps_array_alive(): + A = Array(Signed) + ptr = malloc(A, 10, immortal=True) + ptr2 = direct_arrayitems(ptr) + del ptr + import gc; gc.collect(); gc.collect() + ptr2[0] = 5 # crashes if the array was deallocated From cfbolz at codespeak.net Sat May 10 13:17:17 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sat, 10 May 2008 13:17:17 +0200 (CEST) Subject: [pypy-svn] r54616 - pypy/extradoc/talk/s3-2008 Message-ID: <20080510111717.8F80A2A8003@codespeak.net> Author: cfbolz Date: Sat May 10 13:17:16 2008 New Revision: 54616 Added: pypy/extradoc/talk/s3-2008/objmodel.pdf (contents, props changed) pypy/extradoc/talk/s3-2008/speed.pdf (contents, props changed) Modified: pypy/extradoc/talk/s3-2008/beamerouterthememy.sty pypy/extradoc/talk/s3-2008/talk.tex Log: some work on the slides Modified: pypy/extradoc/talk/s3-2008/beamerouterthememy.sty ============================================================================== --- pypy/extradoc/talk/s3-2008/beamerouterthememy.sty (original) +++ pypy/extradoc/talk/s3-2008/beamerouterthememy.sty Sat May 10 13:17:16 2008 @@ -25,10 +25,10 @@ \defbeamertemplate*{footline}{split theme} {% \leavevmode% - \hbox{\begin{beamercolorbox}[wd=.5\paperwidth,ht=2.5ex,dp=1.125ex,leftskip=.3cm plus1fill,rightskip=.3cm]{author in head/foot}% + \hbox{\begin{beamercolorbox}[wd=.6\paperwidth,ht=2.5ex,dp=1.125ex,leftskip=.3cm plus1fill,rightskip=.3cm]{author in head/foot}% \usebeamerfont{author in head/foot}\insertshortauthor \end{beamercolorbox}% - \begin{beamercolorbox}[wd=.5\paperwidth,ht=2.5ex,dp=1.125ex,leftskip=.3cm,rightskip=.3cm plus1fil]{title in head/foot}% + \begin{beamercolorbox}[wd=.4\paperwidth,ht=2.5ex,dp=1.125ex,leftskip=.3cm,rightskip=.3cm plus1fil]{title in head/foot}% \usebeamerfont{title in head/foot}\insertshorttitle \end{beamercolorbox}}% \vskip0pt% Added: pypy/extradoc/talk/s3-2008/objmodel.pdf ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/s3-2008/speed.pdf ============================================================================== Binary file. No diff available. Modified: pypy/extradoc/talk/s3-2008/talk.tex ============================================================================== --- pypy/extradoc/talk/s3-2008/talk.tex (original) +++ pypy/extradoc/talk/s3-2008/talk.tex Sat May 10 13:17:16 2008 @@ -15,9 +15,36 @@ \usepackage{times} \usepackage[T1]{fontenc} -\title{Back to the Future in one Week --- Implementing a Smalltalk VM in PyPy} +\title[Back to the Future in one Week] +{% + Back to the Future in one Week ? Implementing a Smalltalk VM in PyPy% +} + +\author[Bolz, Kuhn, Lienhard, Matsakis, Nierstrasz, Renggli, Rigo, Verwaest] +{ + \textcolor{green!50!black}{Carl~Friedrich~Bolz}\inst{1} \and + Adrian~Kuhn\inst{2} \and + Adrian~Lienhard\inst{2} \and + Nicholas~D.~Matsakis\inst{3} \and + Oscar~Nierstrasz\inst{2} \and + Lukas~Renggli\inst{2} \and + Armin~Rigo \and + Toon~Verwaest\inst{2} +} -\author{Carl Friedrich Bolz, Adrian Kuhn, Adrian Lienhard, Nicholas D. Matsakis, Oscar Nierstrasz, Lukas Renggli, Armin Rigo, Toon Verwaest} +\institute[Bern and others] +{ + \inst{2}% + Software Composition Group\\ University of Bern, Switzerland + \and% + \vskip-2mm + \inst{1} + Softwaretechnik und Programmiersprachen\\ Heinrich-Heine-Universit\"at D\"usseldorf + \and% + \vskip-2mm + \inst{3}% + ETH Zurich, Switzerland +} \date{Workshop on Self-sustaining Systems, May 16 2008} @@ -52,77 +79,238 @@ % You might wish to add the option [pausesections] %\end{frame} -\frame{ +\begin{frame} \frametitle{Scope} This talk is about: XXX - \itemize{ + \begin{itemize} \item writing a Squeak implementation \item with eight people \item in five days \item using PyPy - } -} - + \end{itemize} +\end{frame} -\frame{ +\begin{frame} \frametitle{What is PyPy} - \itemize{ + \begin{itemize} \item started as a Python implementation in Python \item developed into a general environment for implementing dynamic languages \item supports the language developer with a lot of infrastructure \item Open Source project, MIT license \item most important goal: abstracting over low-level details \item don't fix decisions about low-level details - } -} + \end{itemize} +\end{frame} -\frame{ +\begin{frame} \frametitle{PyPy's Approach to VM Construction} - \itemize{ + \begin{itemize} \item implement an interpreter for the dynamic language in RPython \item translate this interpreter to a low-level language \item translating inserts low-level details \item a variety of target environment: C, LLVM, JVM, .NET % XXX write about model-driven development? - } + \end{itemize} \pause \begin{block} {What is RPython?} - \itemize{ + \begin{itemize} \item a more static subset of Python \item static enough to enable type inference \item still rather expressive: exceptions, inheritance, dynamic dispatch \item analysis starts after importing of interpreter \item enables compile-time metaprogramming - } + \end{itemize} \end{block} -} +\end{frame} -\frame{ +\begin{frame} \begin{block} {Translation Aspects} - \itemize{ + \begin{itemize} \item many aspects of the final VM are orthogonal to language semantics \item examples: GC strategy, threading model, many object details \item non-trivial translation aspect: auto-generating a dynamic compiler \item those shouldn't manifest in the interpreter source \item they are inserted during translation - } + \end{itemize} \end{block} \pause \begin{block} {Compile-Time Metaprogramming} - \itemize{ + \begin{itemize} \item PyPy's translation toolchain starts analysis after importing \item arbitrary (non-RPython) code can be executed during import \item this allows metaprogramming of parts of the interpreter - } + \end{itemize} \end{block} -} +\end{frame} -\frame{ +\begin{frame} \frametitle{The SPy VM} - \itemize{ - \item foo - } + \begin{itemize} + \item really simple, straight-forward Squeak interpreter in RPython + \item essentially free of low-level details, no GC + \item written in the course of five days + \item sprint-driven development + \end{itemize} + \pause + \begin{block} {Status} + \begin{itemize} + \item bytecodes fully implemented + \item many primitives implemented: arithmetic primitives, object primitives + \item can load Squeak images by decoding the bit patterns + \item runs simple benchmarks + \end{itemize} + \end{block} +\end{frame} + +\begin{frame} + \frametitle{SPy Object Model} + \includegraphics[height=5cm]{objmodel} +\end{frame} + +\begin{frame} + \frametitle{Shadows} + Problem: + \begin{itemize} + \item classes are just objects: can't really say which objects are used as classes + \item any object with the right instance fields can be used as a class + \item cryptic bitfields in the class which the VM needs to decode all the time + \end{itemize} + \pause + \begin{block}{Shadows} + \begin{itemize} + \item approach: potentially attach a \emph{shadow} to every object + \item the shadow caches VM-internal information + \item when the object is changed, the shadow is invalidated + \item so far only used for classes, later contexts, methods + \item conceptual cleanliness and nicer VM implementation + \end{itemize} + \end{block} +\end{frame} + +\begin{frame} + \frametitle{Tagged Pointers} + \begin{itemize} + \item Squeak implements integers as tagged pointers + \item doing that is orthogonal to language semantics + \item in PyPy implemented as a translation aspect + \item one class with exactly one int field can be implemented with a flag + \item when enabled, all method calls check for tag first + \item usually changing such a decision would be a major effort + \end{itemize} + \pause + \begin{block}{Results} + \begin{itemize} + \item small slowdown + \item memory advantage not measured + \item really easy to do + \end{itemize} + \end{block} +\end{frame} + +\begin{frame} + \frametitle{Primitives} + \begin{itemize} + \item try to make writing primitives easy + \item failure signaled by an exception + \item automatic popping from the stack and unwrapping of arguments + \item automatic pushing of the result + \item using a custom decorator \texttt{expose\_primitive} + \item compile-time metaprogramming + \end{itemize} +\end{frame} + +\frame[containsverbatim, plain, shrink=10]{ + \begin{verbatim} +bool_ops = [ + (LESSTHAN, operator.lt), + (GREATERTHAN, operator.gt), + (LESSOREQUAL, operator.le), + (GREATEROREQUAL,operator.ge), + (EQUAL, operator.eq), + (NOTEQUAL, operator.ne) + ] + + +def make_func(code, op): + + @expose_primitive(code, unwrap_spec=[int, int]) + def func(interp, v1, v2): + res = op(v1, v2) + w_res = utility.wrap_bool(res) + return w_res + +for (code, op) in bool_ops: + make_func(code, op) + \end{verbatim} } -\end{document} +\begin{frame} + \frametitle{Image Loading} + \begin{itemize} + \item manual decoding of Squeak images by reading Squeak object format + \item image writing could be done in the same way later + \item not really a reason to directly use a memory dump + \item (hard anyway, on object-oriented platforms) + \end{itemize} +\end{frame} +\frame[plain]{ + \frametitle{Performance (tiny Benchmark)} + \includegraphics[height=8cm]{speed} +} + +\begin{frame} + \frametitle{Results} + {\bf Good Points of the Approach:} + \begin{itemize} + \item simple, understandable, high-level Squeak implementation + \item mostly free of low-level details: no GC, no manual pointer tagging + \item written in a short amount of time + \item runs on various platforms + \end{itemize} + \pause + {\bf Bad Points of the Approach:} + \begin{itemize} + \item not really fast (yet) + \item XXX XXX + \end{itemize} +\end{frame} + +\begin{frame} + \frametitle{Outlook} + \begin{itemize} + \item do graphical builtins, to actually start the full environment + \item Squeak-specific optimizations: + \item method-cache (should be easy with shadows) + \item JIT (see next slide) + \item lessons learned for a "SqueaSquea"? + \end{itemize} +\end{frame} + +\begin{frame} + \frametitle{JIT Outlook} + \begin{itemize} + \item PyPy currently explores automatic JIT generation + \item almost orthogonal from the interpreter source ? applicable to many + languages, follows language evolution ``for free'' + \item based on Partial Evaluation techniques + \item benefits from a high-level interpreter + \item generating a dynamic compiler is easier than generating a static one! + \item shares ideas with tracing JITs + \pause + \item current status: basic ideas seem to work, good speedups in prototypes + \item a lot of details still left + \end{itemize} +\end{frame} + +\begin{frame} + \frametitle{Questions?} + \begin{block}{ + PyPy} + \bigskip + \hskip 1cm \url{http://codespeak.net/pypy/} + \bigskip + \end{block} +\end{frame} + +\end{document} From fijal at codespeak.net Sat May 10 13:20:02 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 10 May 2008 13:20:02 +0200 (CEST) Subject: [pypy-svn] r54617 - pypy/branch/io-improvements/pypy/rpython/lltypesystem Message-ID: <20080510112002.D0DE02A8003@codespeak.net> Author: fijal Date: Sat May 10 13:20:02 2008 New Revision: 54617 Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/rstr.py Log: Make sure that we're talking about unsigned here. Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/rstr.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/lltypesystem/rstr.py (original) +++ pypy/branch/io-improvements/pypy/rpython/lltypesystem/rstr.py Sat May 10 13:20:02 2008 @@ -56,6 +56,9 @@ llmemory.sizeof(CHAR_TP) * item) def copy_string_contents(s1, s2, s1start, s2start, lgt): + assert s1start >= 0 + assert s2start >= 0 + assert lgt >= 0 src = llmemory.cast_ptr_to_adr(s1) + _str_ofs(s1start) dest = llmemory.cast_ptr_to_adr(s2) + _str_ofs(s2start) llmemory.raw_memcopy(src, dest, llmemory.sizeof(CHAR_TP) * lgt) @@ -629,7 +632,10 @@ def ll_stringslice_startonly(s1, start): len1 = len(s1.chars) newstr = s1.malloc(len1 - start) - s1.copy_contents(s1, newstr, start, 0, len1 - start) + lgt = len1 - start + assert lgt >= 0 + assert start >= 0 + s1.copy_contents(s1, newstr, start, 0, lgt) return newstr def ll_stringslice(s1, slice): @@ -640,7 +646,10 @@ return s1 stop = len(s1.chars) newstr = s1.malloc(stop - start) - s1.copy_contents(s1, newstr, start, 0, stop - start) + assert start >= 0 + lgt = stop - start + assert lgt >= 0 + s1.copy_contents(s1, newstr, start, 0, lgt) return newstr def ll_stringslice_minusone(s1): From arigo at codespeak.net Sat May 10 13:25:37 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 10 May 2008 13:25:37 +0200 (CEST) Subject: [pypy-svn] r54618 - pypy/dist/pypy/translator/goal Message-ID: <20080510112537.BA79B2A8086@codespeak.net> Author: arigo Date: Sat May 10 13:25:37 2008 New Revision: 54618 Modified: pypy/dist/pypy/translator/goal/gcbench.py Log: Change this test, which fails in a jvm translation probably due to tiny rounding differences. Modified: pypy/dist/pypy/translator/goal/gcbench.py ============================================================================== --- pypy/dist/pypy/translator/goal/gcbench.py (original) +++ pypy/dist/pypy/translator/goal/gcbench.py Sat May 10 13:25:37 2008 @@ -132,7 +132,7 @@ for d in depths: time_construction(d) - if long_lived_tree is None or array[1000] != 1.0/1000: + if long_lived_tree is None or array[1024] != 1.0/1024: println("FAILED") return From arigo at codespeak.net Sat May 10 14:42:53 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 10 May 2008 14:42:53 +0200 (CEST) Subject: [pypy-svn] r54619 - pypy/extradoc/talk/s3-2008 Message-ID: <20080510124253.E06202A8086@codespeak.net> Author: arigo Date: Sat May 10 14:42:51 2008 New Revision: 54619 Modified: pypy/extradoc/talk/s3-2008/talk.tex Log: Put these two lines in a block (it's too easy to miss their apparition in the slide after the pause). Modified: pypy/extradoc/talk/s3-2008/talk.tex ============================================================================== --- pypy/extradoc/talk/s3-2008/talk.tex (original) +++ pypy/extradoc/talk/s3-2008/talk.tex Sat May 10 14:42:51 2008 @@ -297,10 +297,14 @@ \item benefits from a high-level interpreter \item generating a dynamic compiler is easier than generating a static one! \item shares ideas with tracing JITs - \pause - \item current status: basic ideas seem to work, good speedups in prototypes - \item a lot of details still left \end{itemize} + \pause + \begin{block} {Current status} + \begin{itemize} + \item basic ideas seem to work, good speedups in prototypes + \item a lot of details still left + \end{itemize} + \end{block} \end{frame} \begin{frame} From arigo at codespeak.net Sat May 10 15:00:51 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 10 May 2008 15:00:51 +0200 (CEST) Subject: [pypy-svn] r54620 - pypy/dist/pypy/translator/jvm/src/pypy Message-ID: <20080510130051.1986E2A80A8@codespeak.net> Author: arigo Date: Sat May 10 15:00:50 2008 New Revision: 54620 Modified: pypy/dist/pypy/translator/jvm/src/pypy/VoidArray.java Log: Make this class public. At least tor me, it seems to be needed for "java pypy.Main" to start. Modified: pypy/dist/pypy/translator/jvm/src/pypy/VoidArray.java ============================================================================== --- pypy/dist/pypy/translator/jvm/src/pypy/VoidArray.java (original) +++ pypy/dist/pypy/translator/jvm/src/pypy/VoidArray.java Sat May 10 15:00:50 2008 @@ -1,6 +1,6 @@ package pypy; -class VoidArray { +public class VoidArray { public final int length; public VoidArray(int length) { @@ -21,4 +21,4 @@ public void ll_setitem_fast(int index) { } -} \ No newline at end of file +} From fijal at codespeak.net Sat May 10 15:37:34 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 10 May 2008 15:37:34 +0200 (CEST) Subject: [pypy-svn] r54621 - pypy/branch/io-improvements/pypy/rpython/lltypesystem Message-ID: <20080510133734.79DFA2A80AB@codespeak.net> Author: fijal Date: Sat May 10 15:37:32 2008 New Revision: 54621 Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/rstr.py Log: a missing assert Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/rstr.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/lltypesystem/rstr.py (original) +++ pypy/branch/io-improvements/pypy/rpython/lltypesystem/rstr.py Sat May 10 15:37:32 2008 @@ -655,6 +655,7 @@ def ll_stringslice_minusone(s1): newlen = len(s1.chars) - 1 newstr = s1.malloc(newlen) + assert newlen >= 0 s1.copy_contents(s1, newstr, 0, 0, newlen) return newstr From fijal at codespeak.net Sat May 10 17:07:13 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 10 May 2008 17:07:13 +0200 (CEST) Subject: [pypy-svn] r54624 - in pypy/branch/io-improvements/pypy/rlib: . test Message-ID: <20080510150713.B56BD49823B@codespeak.net> Author: fijal Date: Sat May 10 17:07:12 2008 New Revision: 54624 Modified: pypy/branch/io-improvements/pypy/rlib/rstring.py pypy/branch/io-improvements/pypy/rlib/test/test_rstring.py Log: UnicodeBuilder Modified: pypy/branch/io-improvements/pypy/rlib/rstring.py ============================================================================== --- pypy/branch/io-improvements/pypy/rlib/rstring.py (original) +++ pypy/branch/io-improvements/pypy/rlib/rstring.py Sat May 10 17:07:12 2008 @@ -7,16 +7,21 @@ INIT_SIZE = 100 # XXX tweak -class StringBuilder(object): +class AbstractStringBuilder(object): def __init__(self, init_size=INIT_SIZE): self.l = [] def append(self, s): self.l.append(s) +class StringBuilder(AbstractStringBuilder): def build(self): return "".join(self.l) +class UnicodeBuilder(AbstractStringBuilder): + def build(self): + return u''.join(self.l) + class StringBuilderEntry(ExtRegistryEntry): _about_ = StringBuilder @@ -31,3 +36,6 @@ def specialize_call(self, hop): return hop.r_result.rtyper_new(hop) + +class UnicodeBuilderEntry(ExtRegistryEntry): + pass Modified: pypy/branch/io-improvements/pypy/rlib/test/test_rstring.py ============================================================================== --- pypy/branch/io-improvements/pypy/rlib/test/test_rstring.py (original) +++ pypy/branch/io-improvements/pypy/rlib/test/test_rstring.py Sat May 10 17:07:12 2008 @@ -1,6 +1,5 @@ -from pypy.rlib.rstring import StringBuilder -from +from pypy.rlib.rstring import StringBuilder, UnicodeBuilder def test_string_builder(): s = StringBuilder() @@ -8,3 +7,11 @@ s.append("abc") s.append("a") assert s.build() == "aabca" + +def test_unicode_builder(): + s = UnicodeBuilder() + s.append(u'a') + s.append(u'abc') + s.append(u'abcdef') + assert s.build() == 'aabcabcdef' + assert isinstance(s.build(), unicode) From fijal at codespeak.net Sat May 10 17:32:33 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 10 May 2008 17:32:33 +0200 (CEST) Subject: [pypy-svn] r54625 - in pypy/branch/io-improvements/pypy/rpython: . lltypesystem ootypesystem test Message-ID: <20080510153233.38032498001@codespeak.net> Author: fijal Date: Sat May 10 17:32:32 2008 New Revision: 54625 Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/rbuilder.py pypy/branch/io-improvements/pypy/rpython/ootypesystem/rbuilder.py pypy/branch/io-improvements/pypy/rpython/rbuilder.py pypy/branch/io-improvements/pypy/rpython/test/test_rbuilder.py Log: Support for unicode StringBuilder Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/rbuilder.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/lltypesystem/rbuilder.py (original) +++ pypy/branch/io-improvements/pypy/rpython/lltypesystem/rbuilder.py Sat May 10 17:32:32 2008 @@ -1,7 +1,7 @@ from pypy.rpython.rbuilder import AbstractStringBuilderRepr from pypy.rpython.lltypesystem import lltype -from pypy.rpython.lltypesystem.rstr import STR +from pypy.rpython.lltypesystem.rstr import STR, UNICODE from pypy.rpython.annlowlevel import llstr from pypy.rlib import rgc @@ -10,20 +10,22 @@ ('used', lltype.Signed), ('buf', lltype.Ptr(STR))) -class StringBuilderRepr(AbstractStringBuilderRepr): - lowleveltype = lltype.Ptr(STRINGBUILDER) - - @staticmethod - def ll_new(init_size): - ll_builder = lltype.malloc(STRINGBUILDER) +UNICODEBUILDER = lltype.GcStruct('unicodebuilder', + ('allocated', lltype.Signed), + ('used', lltype.Signed), + ('buf', lltype.Ptr(UNICODE))) + +class BaseStringBuilderRepr(AbstractStringBuilderRepr): + @classmethod + def ll_new(cls, init_size): + ll_builder = lltype.malloc(cls.lowleveltype.TO) ll_builder.allocated = init_size ll_builder.used = 0 - ll_builder.buf = rgc.resizable_buffer_of_shape(STR, init_size) + ll_builder.buf = rgc.resizable_buffer_of_shape(cls.basetp, init_size) return ll_builder @staticmethod - def ll_append(ll_builder, str): - ll_str = llstr(str) + def ll_append(ll_builder, ll_str): used = ll_builder.used lgt = len(ll_str.chars) allocated = ll_builder.allocated @@ -53,4 +55,13 @@ final_size = ll_builder.used return rgc.finish_building_buffer(ll_builder.buf, final_size) +class StringBuilderRepr(BaseStringBuilderRepr): + lowleveltype = lltype.Ptr(STRINGBUILDER) + basetp = STR + +class UnicodeBuilderRepr(BaseStringBuilderRepr): + lowleveltype = lltype.Ptr(UNICODEBUILDER) + basetp = UNICODE + +unicodebuilder_repr = UnicodeBuilderRepr() stringbuilder_repr = StringBuilderRepr() Modified: pypy/branch/io-improvements/pypy/rpython/ootypesystem/rbuilder.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/ootypesystem/rbuilder.py (original) +++ pypy/branch/io-improvements/pypy/rpython/ootypesystem/rbuilder.py Sat May 10 17:32:32 2008 @@ -2,12 +2,10 @@ from pypy.rpython.rbuilder import AbstractStringBuilderRepr from pypy.rpython.ootypesystem import ootype -class StringBuilderRepr(AbstractStringBuilderRepr): - lowleveltype = ootype.StringBuilder - - @staticmethod - def ll_new(init_size): - return ootype.new(ootype.StringBuilder) +class BaseBuilderRepr(AbstractStringBuilderRepr): + @classmethod + def ll_new(cls, init_size): + return ootype.new(cls.lowleveltype) @staticmethod def ll_append_char(builder, char): @@ -21,4 +19,11 @@ def ll_build(builder): return builder.ll_build() +class StringBuilderRepr(BaseBuilderRepr): + lowleveltype = ootype.StringBuilder + +class UnicodeBuilderRepr(BaseBuilderRepr): + lowleveltype = ootype.UnicodeBuilder + stringbuilder_repr = StringBuilderRepr() +unicodebuilder_repr = UnicodeBuilderRepr() Modified: pypy/branch/io-improvements/pypy/rpython/rbuilder.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/rbuilder.py (original) +++ pypy/branch/io-improvements/pypy/rpython/rbuilder.py Sat May 10 17:32:32 2008 @@ -1,22 +1,31 @@ from pypy.annotation.model import SomeObject, SomeString, s_None,\ - SomeChar, SomeInteger + SomeChar, SomeInteger, SomeUnicodeCodePoint, SomeUnicodeString from pypy.rpython.rmodel import Repr from pypy.rpython.annlowlevel import llhelper from pypy.rpython.lltypesystem import lltype class SomeStringBuilder(SomeObject): - def __init__(self, init_size): + def __init__(self, init_size, use_unicode=False): self.init_size = init_size + self.use_unicode = use_unicode def method_append(self, s_str): - assert isinstance(s_str, (SomeString, SomeChar)) + if self.use_unicode: + assert isinstance(s_str, (SomeUnicodeCodePoint, SomeUnicodeString)) + else: + assert isinstance(s_str, (SomeString, SomeChar)) return s_None def method_build(self): - return SomeString() + if self.use_unicode: + return SomeUnicodeString() + else: + return SomeString() def rtyper_makerepr(self, rtyper): + if self.use_unicode: + return rtyper.type_system.rbuilder.unicodebuilder_repr return rtyper.type_system.rbuilder.stringbuilder_repr class AbstractStringBuilderRepr(Repr): @@ -30,7 +39,7 @@ def rtype_method_append(self, hop): vlist = hop.inputargs(*hop.args_r) - if isinstance(hop.args_s[1], SomeChar): + if isinstance(hop.args_s[1], (SomeChar, SomeUnicodeCodePoint)): return hop.gendirectcall(self.ll_append_char, *vlist) return hop.gendirectcall(self.ll_append, *vlist) Modified: pypy/branch/io-improvements/pypy/rpython/test/test_rbuilder.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/test/test_rbuilder.py (original) +++ pypy/branch/io-improvements/pypy/rpython/test/test_rbuilder.py Sat May 10 17:32:32 2008 @@ -1,6 +1,6 @@ from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin -from pypy.rlib.rstring import StringBuilder +from pypy.rlib.rstring import StringBuilder, UnicodeBuilder class BaseTestStringBuilder(BaseRtypingTest): def test_simple(self): @@ -22,6 +22,18 @@ res = self.ll_to_string(self.interpret(func, [])) assert res == "abcddefgrty" + def test_unicode(self): + def func(): + s = UnicodeBuilder() + s.append(u'a') + s.append(u'abc') + s.append(u'abcdef') + return s.build() + res = self.ll_to_unicode(self.interpret(func, [])) + assert res == 'aabcabcdef' + assert isinstance(res, unicode) + + class TestLLtype(BaseTestStringBuilder, LLRtypeMixin): pass From fijal at codespeak.net Sat May 10 17:45:23 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 10 May 2008 17:45:23 +0200 (CEST) Subject: [pypy-svn] r54626 - pypy/branch/hybrid-io Message-ID: <20080510154523.CCC2A168568@codespeak.net> Author: fijal Date: Sat May 10 17:45:22 2008 New Revision: 54626 Added: pypy/branch/hybrid-io/ - copied from r54625, pypy/dist/ Log: A branch to experiment with hybrid gc and io-improvements. From cami at codespeak.net Sat May 10 18:32:43 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Sat, 10 May 2008 18:32:43 +0200 (CEST) Subject: [pypy-svn] r54627 - in pypy/branch/gameboy-emulator/pypy/lang/gameboy: . test Message-ID: <20080510163243.92CE42A80A1@codespeak.net> Author: cami Date: Sat May 10 18:32:43 2008 New Revision: 54627 Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/joypad.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cartridge.py Log: fixed some broken tests Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py Sat May 10 18:32:43 2008 @@ -74,7 +74,7 @@ if self.cartridge.has_battery(): self.ram = self.cartridge.read_battery() - def save(self, cartridgeName): + def save(self, cartridge_name): if self.cartridge.has_battery(): self.cartridge.write_battery(self.ram) @@ -147,62 +147,63 @@ self.load(file) def reset(self): - self.cartridgeName ="" - self.cartridgeFilePath = "" - self.cartridgeFile = None - self.batteryName ="" - self.batteryFilePath = "" - self.batteryFile = None - - - def load(self, cartridgeFilePath): - self.cartridgeFilePath = str(cartridgeFilePath) - # self.cartridgeName = os.path.basename(self.cartridgeFilePath) - self.cartridgeFile = open(self.cartridgeFilePath) - self._load_battery(self.cartridgeFilePath) - - - def _load_battery(self, cartridgeFilePath): - self.batteryFilePath = self._create_battery_file_path(cartridgeFilePath) - self.batteryName = os.path.basename(self.batteryFilePath) + self.cartridge_name = None + self.cartridge_file_path = None + self.cartridge_file = None + self.battery_name = None + self.battery_file_path = None + self.battery_file = None + + + def load(self, cartridge_file_path): + cartridge_file_path = str(cartridge_file_path) + self.cartridge_file_path = cartridge_file_path + self.cartridge_name = os.path.basename(self.cartridge_file_path) + self.cartridge_file = open(cartridge_file_path) + self._load_battery(cartridge_file_path) + + + def _load_battery(self, cartridge_file_path): + self.battery_file_path = self._create_battery_file_path(cartridge_file_path) + self.battery_name = os.path.basename(self.battery_file_path) if self.has_battery(): - self.batteryFile = open(self.batteryFilePath) + self.battery_file = open(self.battery_file_path) - def _create_battery_file_path(self, cartridgeFilePath): - if cartridgeFilePath.endswith(constants.CARTRIDGE_FILE_EXTENSION): - return cartridgeFilePath.replace(constants.CARTRIDGE_FILE_EXTENSION, + def _create_battery_file_path(self, cartridge_file_path): + if cartridge_file_path.endswith(constants.CARTRIDGE_FILE_EXTENSION): + return cartridge_file_path.replace(constants.CARTRIDGE_FILE_EXTENSION, constants.BATTERY_FILE_EXTENSION) - elif cartridgeFilePath.endswith(constants.CARTRIDGE_COLOR_FILE_EXTENSION): - return cartridgeFilePath.replace(constants.CARTRIDGE_COLOR_FILE_EXTENSION, + elif cartridge_file_path.endswith(constants.CARTRIDGE_COLOR_FILE_EXTENSION): + return cartridge_file_path.replace(constants.CARTRIDGE_COLOR_FILE_EXTENSION, constants.BATTERY_FILE_EXTENSION) else: - return cartridgeFilePath + constants.BATTERY_FILE_EXTENSION + return cartridge_file_path + constants.BATTERY_FILE_EXTENSION def has_battery(self): - return os.path.exists(self.batteryFilePath) + return os.path.exists(self.battery_file_path) def read(self): - self.cartridgeFile.seek(0) - return map(map_to_byte, self.cartridgeFile.read()) + self.cartridge_file.seek(0) + return map(map_to_byte, self.cartridge_file.read()) def read_battery(self): - self.batteryFile.seek(0) - return map(map_to_byte, self.batteryFile.read()) + self.battery_file.seek(0) + return map(map_to_byte, self.battery_file.read()) def write_battery(self, ram): - self.batteryFile = open(self.batteryFilePath, "w") - self.batteryFile.write(("").join(map(chr, ram))) - self.batteryFile = open(self.batteryFilePath, "r+") + self.battery_file = open(self.battery_file_path, "w") + self.battery_file.write(("").join(map(chr, ram))) + self.battery_file = open(self.battery_file_path, "r+") def remove_battery(self): if self.has_battery(): - os.remove(self.batteryFilePath) + os.remove(self.battery_file_path) def get_size(self): - return os.path.getsize(self.cartridgeFilePath) + return os.path.getsize(self.cartridge_file_path) def get_battery_size(self): - return os.path.getsize(self.batteryFilePath) + return os.path.getsize(self.battery_file_path) Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/joypad.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/joypad.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/joypad.py Sat May 10 18:32:43 2008 @@ -1,5 +1,6 @@ from pypy.lang.gameboy import constants +from pypy.lang.gameboy.interrupt import * class Joypad(object): """ @@ -9,6 +10,8 @@ """ def __init__(self, joypad_driver, interrupt): + assert isinstance(joypad_driver, JoypadDriver) + assert isinstance(interrupt, Interrupt ) self.driver = joypad_driver self.interrupt = interrupt self.reset() Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py Sat May 10 18:32:43 2008 @@ -173,6 +173,7 @@ def __init__(self, sample_rate, frequency_table): Channel.__init__(self, sample_rate, frequency_table) + assert isinstance(sample_rate, int) self.audio_2_index = 0 self.audio_2_length = 0 self.audio_volume = 0 Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cartridge.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cartridge.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cartridge.py Sat May 10 18:32:43 2008 @@ -43,13 +43,13 @@ def test_cartridge_init(): cartridge = get_cartridge() - assert cartridge.cartridgeName == "" - assert cartridge.cartridgeFilePath == "" - assert cartridge.cartridgeFile == None - - assert cartridge.batteryName == "" - assert cartridge.batteryFilePath == "" - assert cartridge.batteryFile == None + assert cartridge.cartridge_name is None + assert cartridge.cartridge_file_path is None + assert cartridge.cartridge_file is None + + assert cartridge.battery_name is None + assert cartridge.battery_file_path is None + assert cartridge.battery_file is None def rest_cartridge_load(): @@ -58,14 +58,14 @@ romFilePath = ROM_PATH+"/rom1/"+romName cartridge.load(romFilePath) - assert cartridge.cartridgeName == romName - assert cartridge.cartridgeFilePath == romFilePath - assert cartridge.cartridgeFile != None + assert cartridge.cartridge_name == romName + assert cartridge.cartridge_file_path == romFilePath + assert cartridge.cartridge_file is not None - assert cartridge.batteryName == romFile+constants.BATTERY_FILE_EXTENSION - assert cartridge.batteryFilePath == romFilePath+constants.BATTERY_FILE_EXTENSION + assert cartridge.battery_name == romFile+constants.BATTERY_FILE_EXTENSION + assert cartridge.battery_file_path == romFilePath+constants.BATTERY_FILE_EXTENSION assert cartridge.has_battery() == False - assert cartridge.batteryFile == None + assert cartridge.battery_file is None def test_cartridge_hasBattery(): @@ -80,7 +80,7 @@ def test_cartridge_read(): cartridge = get_cartridge() - cartridge.cartridgeFile = File(CONTENT) + cartridge.cartridge_file = File(CONTENT) assert cartridge.read() == MAPPED_CONTENT @@ -97,8 +97,8 @@ cartridge.write_battery(MAPPED_CONTENT) assert cartridge.has_battery() == True - print cartridge.batteryFile - assert cartridge.batteryFile.read() == CONTENT + print cartridge.battery_file + assert cartridge.battery_file.read() == CONTENT assert cartridge.read_battery() == MAPPED_CONTENT cartridge.remove_battery() From fijal at codespeak.net Sat May 10 19:18:46 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 10 May 2008 19:18:46 +0200 (CEST) Subject: [pypy-svn] r54630 - pypy/branch/hybrid-io Message-ID: <20080510171846.125FA2A80A1@codespeak.net> Author: fijal Date: Sat May 10 19:18:46 2008 New Revision: 54630 Removed: pypy/branch/hybrid-io/ Log: Delete this branch. copied from wrong place From fijal at codespeak.net Sat May 10 19:20:15 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 10 May 2008 19:20:15 +0200 (CEST) Subject: [pypy-svn] r54631 - pypy/branch/hybrid-io Message-ID: <20080510172015.00E912A80A1@codespeak.net> Author: fijal Date: Sat May 10 19:20:15 2008 New Revision: 54631 Added: pypy/branch/hybrid-io/ - copied from r54630, pypy/branch/io-improvements/ Log: Copy io-improvements to a place where I can play with hybrid gc From arigo at codespeak.net Sat May 10 19:38:47 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 10 May 2008 19:38:47 +0200 (CEST) Subject: [pypy-svn] r54632 - pypy/dist/pypy/doc Message-ID: <20080510173847.484AA2A80AB@codespeak.net> Author: arigo Date: Sat May 10 19:38:44 2008 New Revision: 54632 Modified: pypy/dist/pypy/doc/_ref.txt pypy/dist/pypy/doc/garbage_collection.txt pypy/dist/pypy/doc/index.txt Log: Describe (rough sketch) each of our framework GCs. Modified: pypy/dist/pypy/doc/_ref.txt ============================================================================== --- pypy/dist/pypy/doc/_ref.txt (original) +++ pypy/dist/pypy/doc/_ref.txt Sat May 10 19:38:44 2008 @@ -75,6 +75,10 @@ .. _`pypy/rpython/lltypesystem/lltype.py`: .. _`rpython/lltypesystem/lltype.py`: ../../pypy/rpython/lltypesystem/lltype.py .. _`rpython/memory/`: ../../pypy/rpython/memory +.. _`rpython/memory/gc/generation.py`: ../../pypy/rpython/memory/gc/generation.py +.. _`rpython/memory/gc/hybrid.py`: ../../pypy/rpython/memory/gc/hybrid.py +.. _`rpython/memory/gc/marksweep.py`: ../../pypy/rpython/memory/gc/marksweep.py +.. _`rpython/memory/gc/semispace.py`: ../../pypy/rpython/memory/gc/semispace.py .. _`rpython/ootypesystem/`: ../../pypy/rpython/ootypesystem .. _`rpython/ootypesystem/ootype.py`: ../../pypy/rpython/ootypesystem/ootype.py .. _`rpython/rint.py`: ../../pypy/rpython/rint.py Modified: pypy/dist/pypy/doc/garbage_collection.txt ============================================================================== --- pypy/dist/pypy/doc/garbage_collection.txt (original) +++ pypy/dist/pypy/doc/garbage_collection.txt Sat May 10 19:38:44 2008 @@ -5,12 +5,85 @@ .. contents:: .. sectnum:: +Introduction +============ -**Warning**: The text that was in this document was incomplete and -outdated. A much more up-to-date view of garbage collection in PyPy -can be found in the `EU-report on this topic`_. +**Warning**: The overview and description of our garbage collection +strategy and framework is not here but in the `EU-report on this +topic`_. The present document describes the specific garbage collectors +that we wrote in our framework. .. _`EU-report on this topic`: http://codespeak.net/pypy/extradoc/eu-report/D07.1_Massive_Parallelism_and_Translation_Aspects-2007-02-28.pdf +Garbage collectors currently written for the GC framework +========================================================= +(Very rough sketch only for now.) + +Reminder: to select which GC you want to include in a translated +RPython program, use the ``--gc=NAME`` option of ``translate.py``. +For more details, see the `overview of command line options for +translation`_. + +.. _`overview of command line options for translation`: config/commandline.html#overview-of-command-line-options-for-translation + +Mark and Sweep +-------------- + +Classical Mark and Sweep collector. Also contains a lot of experimental +and half-unmaintained features. See `rpython/memory/gc/marksweep.py`_. + +Semispace copying collector +--------------------------- + +Two arenas of equal size, with only one arena in use and getting filled +with new objects. When the arena is full, the live objects are copied +into the other arena using Cheney's algorithm. The old arena is then +cleared. See `rpython/memory/gc/semispace.py`_. + +On Unix the clearing is done by reading ``/dev/zero`` into the arena, +which is extremely memory efficient at least on Linux: it lets the +kernel free the RAM that the old arena used and replace it all with +allocated-on-demand memory. + +The size of each semispace starts at 8MB but grows as needed when the +amount of objects alive grows. + +Generational GC +--------------- + +This is a two-generations GC. See `rpython/memory/gc/generation.py`_. + +It is implemented as a subclass of the Semispace copying collector. It +adds a nursery, which is a chunk of the current semispace. Its size is +computed to be half the size of the CPU Level 2 cache. Allocations fill +the nursery, and when it is full, it is collected and the objects still +alive are moved to the rest of the current semispace. + +The idea is that it is very common for objects to die soon after they +are created. Generational GCs help a lot in this case, particularly if +the amount of live objects really manipulated by the program fits in the +Level 2 cache. Moreover, the semispaces fill up much more slowly, +making full collections less frequent. + +Hybrid GC +--------- + +This is a three-generations GC. + +It is implemented as a subclass of the Generational GC. The Hybrid GC +can handle both objects that are inside and objects that are outside the +semispaces ("external"). The external objects are not moving and +collected in a mark-and-sweep fashion. Large objects are allocated as +external objects to avoid costly moves. Small objects that survive for +a long enough time (several semispace collections) are also made +external so that they stop moving. + +This is coupled with a segregation of the objects in three generations. +Each generation is collected much less often than the previous one. The +division of the generations is slightly more complicated than just +nursery / semispace / external; see the diagram at the start of the +source code, in `rpython/memory/gc/hybrid.py`_. + +.. include:: _ref.txt Modified: pypy/dist/pypy/doc/index.txt ============================================================================== --- pypy/dist/pypy/doc/index.txt (original) +++ pypy/dist/pypy/doc/index.txt Sat May 10 19:38:44 2008 @@ -136,6 +136,9 @@ properties into our interpreter during the translation process. This document is also part of the `EU reports`_. +`garbage collector`_ strategies that can be used by the virtual +machines produced by the translation process. + `parser`_ contains (outdated, unfinished) documentation about the parser. @@ -271,7 +274,7 @@ `rpython/ootypesystem/`_ the `object-oriented type system`_ for OO backends -`rpython/memory/`_ the garbage collector construction framework +`rpython/memory/`_ the `garbage collector`_ construction framework `tool/`_ various utilities and hacks used from various places @@ -346,6 +349,7 @@ .. _rtyper: rtyper.html .. _`low-level type system`: rtyper.html#low-level-type .. _`object-oriented type system`: rtyper.html#oo-type +.. _`garbage collector`: garbage_collection.html .. _`Stackless Transform`: translation.html#the-stackless-transform .. _`PyPy Prolog Interpreter`: prolog-interpreter.html .. _`Prolog Interpreter`: prolog-interpreter.html From fijal at codespeak.net Sat May 10 20:42:23 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 10 May 2008 20:42:23 +0200 (CEST) Subject: [pypy-svn] r54635 - pypy/branch/io-improvements/pypy/rlib Message-ID: <20080510184223.75ACB69802D@codespeak.net> Author: fijal Date: Sat May 10 20:42:21 2008 New Revision: 54635 Modified: pypy/branch/io-improvements/pypy/rlib/rstring.py Log: use one annotation instead of two. solves messy errors Modified: pypy/branch/io-improvements/pypy/rlib/rstring.py ============================================================================== --- pypy/branch/io-improvements/pypy/rlib/rstring.py (original) +++ pypy/branch/io-improvements/pypy/rlib/rstring.py Sat May 10 20:42:21 2008 @@ -22,20 +22,25 @@ def build(self): return u''.join(self.l) -class StringBuilderEntry(ExtRegistryEntry): - _about_ = StringBuilder - +class BaseEntry(object): def compute_result_annotation(self, s_init_size=None): - from pypy.rpython.rbuilder import SomeStringBuilder + from pypy.rpython.rbuilder import SomeStringBuilder, SomeUnicodeBuilder if s_init_size is not None: assert s_init_size.is_constant() init_size = s_init_size.const else: init_size = INIT_SIZE + if self.use_unicode: + return SomeUnicodeBuilder(init_size) return SomeStringBuilder(init_size) - + def specialize_call(self, hop): return hop.r_result.rtyper_new(hop) -class UnicodeBuilderEntry(ExtRegistryEntry): - pass +class StringBuilderEntry(BaseEntry, ExtRegistryEntry): + _about_ = StringBuilder + use_unicode = False + +class UnicodeBuilderEntry(BaseEntry, ExtRegistryEntry): + _about_ = UnicodeBuilder + use_unicode = True From fijal at codespeak.net Sat May 10 20:42:46 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 10 May 2008 20:42:46 +0200 (CEST) Subject: [pypy-svn] r54636 - pypy/branch/io-improvements/pypy/rpython Message-ID: <20080510184246.4907E69802D@codespeak.net> Author: fijal Date: Sat May 10 20:42:45 2008 New Revision: 54636 Modified: pypy/branch/io-improvements/pypy/rpython/rbuilder.py Log: Different annotations for StringBuilder and UnicodeBuilder Modified: pypy/branch/io-improvements/pypy/rpython/rbuilder.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/rbuilder.py (original) +++ pypy/branch/io-improvements/pypy/rpython/rbuilder.py Sat May 10 20:42:45 2008 @@ -6,28 +6,33 @@ from pypy.rpython.lltypesystem import lltype class SomeStringBuilder(SomeObject): - def __init__(self, init_size, use_unicode=False): + def __init__(self, init_size): self.init_size = init_size - self.use_unicode = use_unicode def method_append(self, s_str): - if self.use_unicode: - assert isinstance(s_str, (SomeUnicodeCodePoint, SomeUnicodeString)) - else: - assert isinstance(s_str, (SomeString, SomeChar)) + assert isinstance(s_str, (SomeString, SomeChar)) return s_None def method_build(self): - if self.use_unicode: - return SomeUnicodeString() - else: - return SomeString() + return SomeString() def rtyper_makerepr(self, rtyper): - if self.use_unicode: - return rtyper.type_system.rbuilder.unicodebuilder_repr return rtyper.type_system.rbuilder.stringbuilder_repr +class SomeUnicodeBuilder(SomeObject): + def __init__(self, init_size): + self.init_size = init_size + + def method_append(self, s_str): + assert isinstance(s_str, (SomeUnicodeCodePoint, SomeUnicodeString)) + return s_None + + def method_build(self): + return SomeUnicodeString() + + def rtyper_makerepr(self, rtyper): + return rtyper.type_system.rbuilder.unicodebuilder_repr + class AbstractStringBuilderRepr(Repr): def rtyper_new(self, hop): repr = hop.r_result From fijal at codespeak.net Sat May 10 22:05:51 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 10 May 2008 22:05:51 +0200 (CEST) Subject: [pypy-svn] r54637 - in pypy/branch/io-improvements/pypy/rlib: . test Message-ID: <20080510200551.1A16C2A8086@codespeak.net> Author: fijal Date: Sat May 10 22:05:50 2008 New Revision: 54637 Modified: pypy/branch/io-improvements/pypy/rlib/rstring.py pypy/branch/io-improvements/pypy/rlib/test/test_rstring.py Log: add to string builder operation append_slice which takes a source string, start and end of slice to add Modified: pypy/branch/io-improvements/pypy/rlib/rstring.py ============================================================================== --- pypy/branch/io-improvements/pypy/rlib/rstring.py (original) +++ pypy/branch/io-improvements/pypy/rlib/rstring.py Sat May 10 22:05:50 2008 @@ -14,6 +14,9 @@ def append(self, s): self.l.append(s) + def append_slice(self, s, start, end): + self.l.append(s[start:end]) + class StringBuilder(AbstractStringBuilder): def build(self): return "".join(self.l) Modified: pypy/branch/io-improvements/pypy/rlib/test/test_rstring.py ============================================================================== --- pypy/branch/io-improvements/pypy/rlib/test/test_rstring.py (original) +++ pypy/branch/io-improvements/pypy/rlib/test/test_rstring.py Sat May 10 22:05:50 2008 @@ -6,12 +6,13 @@ s.append("a") s.append("abc") s.append("a") - assert s.build() == "aabca" + s.append_slice("abc", 1, 2) + assert s.build() == "aabcab" def test_unicode_builder(): s = UnicodeBuilder() s.append(u'a') s.append(u'abc') - s.append(u'abcdef') - assert s.build() == 'aabcabcdef' + s.append_slice(u'abcdef', 1, 2) + assert s.build() == 'aabcb' assert isinstance(s.build(), unicode) From fijal at codespeak.net Sat May 10 22:07:25 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 10 May 2008 22:07:25 +0200 (CEST) Subject: [pypy-svn] r54638 - in pypy/branch/io-improvements/pypy/rlib: . test Message-ID: <20080510200725.4071F2A8086@codespeak.net> Author: fijal Date: Sat May 10 22:07:24 2008 New Revision: 54638 Modified: pypy/branch/io-improvements/pypy/rlib/rstring.py pypy/branch/io-improvements/pypy/rlib/test/test_rstring.py Log: add an append_multiple_char operation as well Modified: pypy/branch/io-improvements/pypy/rlib/rstring.py ============================================================================== --- pypy/branch/io-improvements/pypy/rlib/rstring.py (original) +++ pypy/branch/io-improvements/pypy/rlib/rstring.py Sat May 10 22:07:24 2008 @@ -17,6 +17,9 @@ def append_slice(self, s, start, end): self.l.append(s[start:end]) + def append_multiple_char(self, c, times): + self.l.append(c * times) + class StringBuilder(AbstractStringBuilder): def build(self): return "".join(self.l) Modified: pypy/branch/io-improvements/pypy/rlib/test/test_rstring.py ============================================================================== --- pypy/branch/io-improvements/pypy/rlib/test/test_rstring.py (original) +++ pypy/branch/io-improvements/pypy/rlib/test/test_rstring.py Sat May 10 22:07:24 2008 @@ -7,12 +7,14 @@ s.append("abc") s.append("a") s.append_slice("abc", 1, 2) - assert s.build() == "aabcab" + s.append_multiple_char('d', 4) + assert s.build() == "aabcabdddd" def test_unicode_builder(): s = UnicodeBuilder() s.append(u'a') s.append(u'abc') s.append_slice(u'abcdef', 1, 2) - assert s.build() == 'aabcb' + s.append_multiple_char('d', 4) + assert s.build() == 'aabcbdddd' assert isinstance(s.build(), unicode) From fijal at codespeak.net Sat May 10 22:28:08 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 10 May 2008 22:28:08 +0200 (CEST) Subject: [pypy-svn] r54639 - in pypy/branch/io-improvements/pypy/rpython: . lltypesystem ootypesystem test Message-ID: <20080510202808.2876F2A8086@codespeak.net> Author: fijal Date: Sat May 10 22:28:07 2008 New Revision: 54639 Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/rbuilder.py pypy/branch/io-improvements/pypy/rpython/ootypesystem/rbuilder.py pypy/branch/io-improvements/pypy/rpython/rbuilder.py pypy/branch/io-improvements/pypy/rpython/test/test_rbuilder.py Log: Implement append_slice and append_multiple_char for both lltypesystem and ootypesystem Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/rbuilder.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/lltypesystem/rbuilder.py (original) +++ pypy/branch/io-improvements/pypy/rpython/lltypesystem/rbuilder.py Sat May 10 22:28:07 2008 @@ -4,16 +4,28 @@ from pypy.rpython.lltypesystem.rstr import STR, UNICODE from pypy.rpython.annlowlevel import llstr from pypy.rlib import rgc +from pypy.rpython.lltypesystem.lltype import staticAdtMethod +from pypy.tool.sourcetools import func_with_new_name + +def stringbuilder_grow(ll_builder, needed): + # XXX tweak overallocation scheme + new_allocated = ll_builder.allocated + needed + 100 + ll_builder.buf = rgc.resize_buffer(ll_builder.buf, ll_builder.used, + new_allocated) + ll_builder.allocated = new_allocated +stringbuilder_grow._annspecialcase_ = 'specialize:argtype(0)' STRINGBUILDER = lltype.GcStruct('stringbuilder', ('allocated', lltype.Signed), ('used', lltype.Signed), - ('buf', lltype.Ptr(STR))) + ('buf', lltype.Ptr(STR)), + adtmeths={'grow':staticAdtMethod(stringbuilder_grow)}) UNICODEBUILDER = lltype.GcStruct('unicodebuilder', ('allocated', lltype.Signed), ('used', lltype.Signed), - ('buf', lltype.Ptr(UNICODE))) + ('buf', lltype.Ptr(UNICODE)), + adtmeths={'grow':staticAdtMethod(stringbuilder_grow)}) class BaseStringBuilderRepr(AbstractStringBuilderRepr): @classmethod @@ -28,29 +40,40 @@ def ll_append(ll_builder, ll_str): used = ll_builder.used lgt = len(ll_str.chars) - allocated = ll_builder.allocated needed = lgt + used - if needed >= allocated: - # XXX tune overallocation scheme - new_allocated = needed + 100 - ll_builder.buf = rgc.resize_buffer(ll_builder.buf, used, - new_allocated) - ll_builder.allocated = new_allocated + if needed >= ll_builder.allocated: + ll_builder.grow(ll_builder, lgt) ll_str.copy_contents(ll_str, ll_builder.buf, 0, used, lgt) - ll_builder.used = used + lgt + ll_builder.used = needed @staticmethod def ll_append_char(ll_builder, char): if ll_builder.used == ll_builder.allocated: - # XXX tune overallocation scheme - new_allocated = ll_builder.allocated + 100 - ll_builder.buf = rgc.resize_buffer(ll_builder.buf, ll_builder.used, - new_allocated) - ll_builder.allocated = new_allocated + ll_builder.grow(ll_builder, 1) ll_builder.buf.chars[ll_builder.used] = char ll_builder.used += 1 @staticmethod + def ll_append_slice(ll_builder, ll_str, start, end): + needed = end - start + used = ll_builder.used + if needed + used >= ll_builder.allocated: + ll_builder.grow(ll_builder, needed) + assert needed >= 0 + ll_str.copy_contents(ll_str, ll_builder.buf, start, used, needed) + ll_builder.used = needed + used + + @staticmethod + def ll_append_multiple_char(ll_builder, char, times): + used = ll_builder.used + if times + used >= ll_builder.allocated: + ll_builder.grow(ll_builder, times) + for i in range(times): + ll_builder.buf.chars[used] = char + used += 1 + ll_builder.used = used + + @staticmethod def ll_build(ll_builder): final_size = ll_builder.used return rgc.finish_building_buffer(ll_builder.buf, final_size) Modified: pypy/branch/io-improvements/pypy/rpython/ootypesystem/rbuilder.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/ootypesystem/rbuilder.py (original) +++ pypy/branch/io-improvements/pypy/rpython/ootypesystem/rbuilder.py Sat May 10 22:28:07 2008 @@ -16,6 +16,17 @@ builder.ll_append(string) @staticmethod + def ll_append_slice(builder, string, start, end): + # XXX not sure how to optimize it + for i in range(start, end): + builder.ll_append_char(string.ll_stritem_nonneg(i)) + + @staticmethod + def ll_append_multiple_char(builder, char, times): + for i in range(times): + builder.ll_append_char(char) + + @staticmethod def ll_build(builder): return builder.ll_build() Modified: pypy/branch/io-improvements/pypy/rpython/rbuilder.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/rbuilder.py (original) +++ pypy/branch/io-improvements/pypy/rpython/rbuilder.py Sat May 10 22:28:07 2008 @@ -13,6 +13,20 @@ assert isinstance(s_str, (SomeString, SomeChar)) return s_None + def method_append_slice(self, s_str, s_start, s_end): + assert isinstance(s_str, SomeString) + assert isinstance(s_start, SomeInteger) + assert isinstance(s_end, SomeInteger) + assert s_start.nonneg + assert s_end.nonneg + return s_None + + def method_append_multiple_char(self, s_char, s_times): + assert isinstance(s_char, SomeChar) + assert isinstance(s_times, SomeInteger) + assert s_times.nonneg + return s_None + def method_build(self): return SomeString() @@ -27,6 +41,20 @@ assert isinstance(s_str, (SomeUnicodeCodePoint, SomeUnicodeString)) return s_None + def method_append_slice(self, s_str, s_start, s_end): + assert isinstance(s_str, SomeUnicodeString) + assert isinstance(s_start, SomeInteger) + assert isinstance(s_end, SomeInteger) + assert s_start.nonneg + assert s_end.nonneg + return s_None + + def method_append_multiple_char(self, s_char, s_times): + assert isinstance(s_char, SomeUnicodeCodePoint) + assert isinstance(s_times, SomeInteger) + assert s_times.nonneg + return s_None + def method_build(self): return SomeUnicodeString() @@ -48,6 +76,14 @@ return hop.gendirectcall(self.ll_append_char, *vlist) return hop.gendirectcall(self.ll_append, *vlist) + def rtype_method_append_slice(self, hop): + vlist = hop.inputargs(*hop.args_r) + return hop.gendirectcall(self.ll_append_slice, *vlist) + + def rtype_method_append_multiple_char(self, hop): + vlist = hop.inputargs(*hop.args_r) + return hop.gendirectcall(self.ll_append_multiple_char, *vlist) + def rtype_method_build(self, hop): vlist = hop.inputargs(*hop.args_r) return hop.gendirectcall(self.ll_build, *vlist) Modified: pypy/branch/io-improvements/pypy/rpython/test/test_rbuilder.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/test/test_rbuilder.py (original) +++ pypy/branch/io-improvements/pypy/rpython/test/test_rbuilder.py Sat May 10 22:28:07 2008 @@ -8,9 +8,11 @@ s = StringBuilder() s.append("a") s.append("abc") + s.append_slice("abc", 1, 2) + s.append_multiple_char('d', 4) return s.build() res = self.ll_to_string(self.interpret(func, [])) - assert res == "aabc" + assert res == "aabcbdddd" def test_overallocation(self): def func(): @@ -28,9 +30,11 @@ s.append(u'a') s.append(u'abc') s.append(u'abcdef') + s.append_slice(u'abc', 1, 2) + s.append_multiple_char(u'u', 4) return s.build() res = self.ll_to_unicode(self.interpret(func, [])) - assert res == 'aabcabcdef' + assert res == 'aabcabcdefbuuuu' assert isinstance(res, unicode) From fijal at codespeak.net Sat May 10 23:43:53 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 10 May 2008 23:43:53 +0200 (CEST) Subject: [pypy-svn] r54640 - pypy/branch/io-improvements/pypy/rpython/lltypesystem Message-ID: <20080510214353.0D881498001@codespeak.net> Author: fijal Date: Sat May 10 23:43:50 2008 New Revision: 54640 Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/rbuilder.py Log: Fix translation Modified: pypy/branch/io-improvements/pypy/rpython/lltypesystem/rbuilder.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/lltypesystem/rbuilder.py (original) +++ pypy/branch/io-improvements/pypy/rpython/lltypesystem/rbuilder.py Sat May 10 23:43:50 2008 @@ -7,13 +7,17 @@ from pypy.rpython.lltypesystem.lltype import staticAdtMethod from pypy.tool.sourcetools import func_with_new_name -def stringbuilder_grow(ll_builder, needed): - # XXX tweak overallocation scheme - new_allocated = ll_builder.allocated + needed + 100 - ll_builder.buf = rgc.resize_buffer(ll_builder.buf, ll_builder.used, - new_allocated) - ll_builder.allocated = new_allocated -stringbuilder_grow._annspecialcase_ = 'specialize:argtype(0)' +def new_grow_func(name): + def stringbuilder_grow(ll_builder, needed): + # XXX tweak overallocation scheme + new_allocated = ll_builder.allocated + needed + 100 + ll_builder.buf = rgc.resize_buffer(ll_builder.buf, ll_builder.used, + new_allocated) + ll_builder.allocated = new_allocated + return func_with_new_name(stringbuilder_grow, name) + +stringbuilder_grow = new_grow_func('stringbuilder_grow') +unicodebuilder_grow = new_grow_func('unicodebuilder_grow') STRINGBUILDER = lltype.GcStruct('stringbuilder', ('allocated', lltype.Signed), @@ -25,7 +29,7 @@ ('allocated', lltype.Signed), ('used', lltype.Signed), ('buf', lltype.Ptr(UNICODE)), - adtmeths={'grow':staticAdtMethod(stringbuilder_grow)}) + adtmeths={'grow':staticAdtMethod(unicodebuilder_grow)}) class BaseStringBuilderRepr(AbstractStringBuilderRepr): @classmethod From fijal at codespeak.net Sun May 11 02:28:26 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 11 May 2008 02:28:26 +0200 (CEST) Subject: [pypy-svn] r54642 - in pypy/branch/io-improvements/pypy/rpython/memory: gctransform test Message-ID: <20080511002826.0F03A2A80AD@codespeak.net> Author: fijal Date: Sun May 11 02:28:25 2008 New Revision: 54642 Modified: pypy/branch/io-improvements/pypy/rpython/memory/gctransform/boehm.py pypy/branch/io-improvements/pypy/rpython/memory/gctransform/transform.py pypy/branch/io-improvements/pypy/rpython/memory/test/test_transformed_gc.py Log: * Make test slightly more verbose * A fix. It's very hard to test since it's about argument for realloc for boehm. We need to have a different gc (like mark'n'sweep) supporting realloc in order to test this correctly. Modified: pypy/branch/io-improvements/pypy/rpython/memory/gctransform/boehm.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/memory/gctransform/boehm.py (original) +++ pypy/branch/io-improvements/pypy/rpython/memory/gctransform/boehm.py Sun May 11 02:28:25 2008 @@ -63,9 +63,9 @@ def _can_realloc(self): return True - def perform_realloc(self, hop, c_const_size, c_item_size, c_lengthofs): - op = hop.spaceop - args = [self.realloc_ptr, op.args[0], op.args[1], c_const_size, + def perform_realloc(self, hop, v_ptr, v_newlgt, c_const_size, c_item_size, + c_lengthofs): + args = [self.realloc_ptr, v_ptr, v_newlgt, c_const_size, c_item_size, c_lengthofs] return hop.genop('direct_call', args, resulttype=llmemory.Address) Modified: pypy/branch/io-improvements/pypy/rpython/memory/gctransform/transform.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/memory/gctransform/transform.py (original) +++ pypy/branch/io-improvements/pypy/rpython/memory/gctransform/transform.py Sun May 11 02:28:25 2008 @@ -542,15 +542,16 @@ return self.varsize_malloc_helper(hop, flags, meth, []) def gct_resize_buffer(self, hop): + op = hop.spaceop if self._can_realloc(): - self._gct_resize_buffer_realloc(hop) + self._gct_resize_buffer_realloc(hop, op.args[2]) else: - self._gct_resize_buffer_no_realloc(hop) + self._gct_resize_buffer_no_realloc(hop, op.args[1]) def _can_realloc(self): return False - def _gct_resize_buffer_realloc(self, hop): + def _gct_resize_buffer_realloc(self, hop, v_newsize): def intconst(c): return rmodel.inputconst(lltype.Signed, c) op = hop.spaceop flags = {'flavor':'gc', 'varsize': True} @@ -562,11 +563,12 @@ c_item_size = intconst(llmemory.sizeof(ARRAY.OF)) c_lengthofs = intconst(offset_to_length) - v_raw = self.perform_realloc(hop, c_const_size, c_item_size, - c_lengthofs) + v_ptr = op.args[0] + v_raw = self.perform_realloc(hop, v_ptr, v_newsize, c_const_size, + c_item_size, c_lengthofs) hop.cast_result(v_raw) - def _gct_resize_buffer_no_realloc(self, hop): + def _gct_resize_buffer_no_realloc(self, hop, v_lgt): op = hop.spaceop meth = self.gct_fv_gc_malloc_varsize flags = {'flavor':'gc', 'varsize': True} @@ -574,7 +576,6 @@ # fish resvar v_newbuf = hop.llops[-1].result v_src = op.args[0] - v_lgt = op.args[1] TYPE = v_src.concretetype.TO c_fldname = rmodel.inputconst(lltype.Void, TYPE._arrayfld) v_adrsrc = hop.genop('cast_ptr_to_adr', [v_src], @@ -598,9 +599,9 @@ def gct_finish_building_buffer(self, hop): op = hop.spaceop if self._can_realloc(): - return self._gct_resize_buffer_realloc(hop) + return self._gct_resize_buffer_realloc(hop, op.args[1]) else: - return self._gct_resize_buffer_no_realloc(hop) + return self._gct_resize_buffer_no_realloc(hop, op.args[1]) def varsize_malloc_helper(self, hop, flags, meth, extraargs): def intconst(c): return rmodel.inputconst(lltype.Signed, c) Modified: pypy/branch/io-improvements/pypy/rpython/memory/test/test_transformed_gc.py ============================================================================== --- pypy/branch/io-improvements/pypy/rpython/memory/test/test_transformed_gc.py (original) +++ pypy/branch/io-improvements/pypy/rpython/memory/test/test_transformed_gc.py Sun May 11 02:28:25 2008 @@ -502,10 +502,10 @@ ptr.chars[0] = 'a' ptr = rgc.resize_buffer(ptr, 1, 200) ptr.chars[1] = 'b' - return len(hlstr(rgc.finish_building_buffer(ptr, 2))) + return hlstr(rgc.finish_building_buffer(ptr, 2)) == "ab" run = self.runner(f) - assert run([]) == 2 + assert run([]) == 1 class GenericMovingGCTests(GenericGCTests): GC_CAN_MOVE = True From fijal at codespeak.net Sun May 11 03:14:08 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 11 May 2008 03:14:08 +0200 (CEST) Subject: [pypy-svn] r54643 - pypy/branch/io-improvements/pypy/objspace/std Message-ID: <20080511011408.81B7D2A8086@codespeak.net> Author: fijal Date: Sun May 11 03:14:05 2008 New Revision: 54643 Modified: pypy/branch/io-improvements/pypy/objspace/std/formatting.py Log: Actually use string builder for '%' formatting. This (for boehm) nicely speeds up microbenchs by 15-35% depending on benchmark used Modified: pypy/branch/io-improvements/pypy/objspace/std/formatting.py ============================================================================== --- pypy/branch/io-improvements/pypy/objspace/std/formatting.py (original) +++ pypy/branch/io-improvements/pypy/objspace/std/formatting.py Sun May 11 03:14:05 2008 @@ -5,7 +5,7 @@ from pypy.rlib.rarithmetic import ovfcheck, formatd_overflow, isnan, isinf from pypy.interpreter.error import OperationError from pypy.tool.sourcetools import func_with_new_name -from pypy.rlib.debug import check_annotation +from pypy.rlib.rstring import StringBuilder, UnicodeBuilder class BaseStringFormatter(object): def __init__(self, space, values_w, w_valuedict): @@ -256,7 +256,10 @@ return result def format(self): - result = [] # list of characters or unichars + if do_unicode: + result = UnicodeBuilder() + else: + result = StringBuilder() self.result = result while True: # fast path: consume as many characters as possible @@ -267,9 +270,9 @@ break i += 1 else: - result += const(fmt[i0:]) - break # end of 'fmt' string - result += const(fmt[i0:i]) + result.append_slice(fmt, i0, len(fmt)) + break # end of 'fmt' string + result.append_slice(fmt, i0, i) self.fmtpos = i + 1 # interpret the next formatter @@ -295,7 +298,7 @@ self.unknown_fmtchar() self.checkconsumed() - return result + return result.build() def unknown_fmtchar(self): space = self.space @@ -316,22 +319,28 @@ def std_wp(self, r): length = len(r) + if do_unicode and isinstance(r, str): + # convert string to unicode explicitely here + r = unicode(r) prec = self.prec if prec == -1 and self.width == 0: # fast path - self.result += const(r) + self.result.append(const(r)) return if prec >= 0 and prec < length: length = prec # ignore the end of the string if too long result = self.result padding = self.width - length + if padding < 0: + padding = 0 + assert padding >= 0 if not self.f_ljust and padding > 0: - result += const(' ') * padding + result.append_multiple_char(const(' '), padding) # add any padding at the left of 'r' padding = 0 - result += const(r[:length]) # add 'r' itself + result.append_slice(r, 0, length) # add 'r' itself if padding > 0: - result += const(' ') * padding + result.append_multiple_char(const(' '), padding) # add any remaining padding at the right std_wp._annspecialcase_ = 'specialize:argtype(1)' @@ -350,6 +359,8 @@ # by pushing the pad character into self.result result = self.result padding = self.width - len(r) - len(prefix) + if padding <= 0: + padding = 0 if self.f_ljust: padnumber = '<' @@ -358,16 +369,20 @@ else: padnumber = '>' + assert padding >= 0 if padnumber == '>': - result += const(' ') * padding # pad with spaces on the left + result.append_multiple_char(const(' '), padding) + # pad with spaces on the left if sign: - result += const(r[0]) # the sign - result += const(prefix) # the prefix + result.append(const(r[0])) # the sign + result.append(const(prefix)) # the prefix if padnumber == '0': - result += const('0') * padding # pad with zeroes - result += const(r[int(sign):]) # the rest of the number + result.append_multiple_char(const('0'), padding) + # pad with zeroes + result.append_slice(const(r), int(sign), len(r)) + # the rest of the number if padnumber == '<': # spaces on the right - result += const(' ') * padding + result.append_multiple_char(const(' '), padding) def fmt_s(self, w_value): space = self.space @@ -454,14 +469,12 @@ # fall through to the unicode case fmt = unicode(fmt) else: - check_annotation(result, is_list_of_chars_or_unichars) - return space.wrap(''.join(result)) + return space.wrap(result) else: fmt = space.unicode_w(w_fmt) formatter = UnicodeFormatter(space, fmt, values_w, w_valuedict) result = formatter.format() - check_annotation(result, is_list_of_chars_or_unichars) - return space.wrap(u''.join(result)) + return space.wrap(result) def mod_format(space, w_format, w_values, do_unicode=False): if space.is_true(space.isinstance(w_values, space.w_tuple)): From xoraxax at codespeak.net Sun May 11 11:41:33 2008 From: xoraxax at codespeak.net (xoraxax at codespeak.net) Date: Sun, 11 May 2008 11:41:33 +0200 (CEST) Subject: [pypy-svn] r54644 - pypy/extradoc/planning/roadmap Message-ID: <20080511094133.A910016A0CD@codespeak.net> Author: xoraxax Date: Sun May 11 11:41:31 2008 New Revision: 54644 Modified: pypy/extradoc/planning/roadmap/goal_cpython_replacement.txt pypy/extradoc/planning/roadmap/task_catch_up_with_2_x.txt pypy/extradoc/planning/roadmap/task_ctypes.txt pypy/extradoc/planning/roadmap/task_manual_optimizations.txt pypy/extradoc/planning/roadmap/task_multi_platform.txt pypy/extradoc/planning/roadmap/task_refactor_jit.txt Log: Moved jit in the goal file, updated a few tasks, fixed rest errors. Modified: pypy/extradoc/planning/roadmap/goal_cpython_replacement.txt ============================================================================== --- pypy/extradoc/planning/roadmap/goal_cpython_replacement.txt (original) +++ pypy/extradoc/planning/roadmap/goal_cpython_replacement.txt Sun May 11 11:41:31 2008 @@ -11,10 +11,6 @@ These tasks are loosley ordered by categories (speed, extra features, external modules) (XXX: have a more structured outline?) -.. include:: task_refactor_jit.txt - -.. include:: task_optimize_jit.txt - .. include:: task_manual_optimizations.txt .. include:: task_multi_platform.txt @@ -29,6 +25,11 @@ .. include:: task_ctypes.txt +.. include:: task_refactor_jit.txt + +.. include:: task_optimize_jit.txt + + .. include:: task_wrapper_generator.txt .. include:: task_cpython_api.txt Modified: pypy/extradoc/planning/roadmap/task_catch_up_with_2_x.txt ============================================================================== --- pypy/extradoc/planning/roadmap/task_catch_up_with_2_x.txt (original) +++ pypy/extradoc/planning/roadmap/task_catch_up_with_2_x.txt Sun May 11 11:41:31 2008 @@ -5,6 +5,7 @@ - PyPy already implements a few features of 2.5 (PEP 309, PEP 338, PEP 341, PEP 357, partition, any, all) + - Currently underway (Google SOC 2008 project) todo: - Implement these features that were new in CPython 2.5: Modified: pypy/extradoc/planning/roadmap/task_ctypes.txt ============================================================================== --- pypy/extradoc/planning/roadmap/task_ctypes.txt (original) +++ pypy/extradoc/planning/roadmap/task_ctypes.txt Sun May 11 11:41:31 2008 @@ -2,6 +2,7 @@ ======================== status: + - Done (with a few minor exceptions). todo: - As a first approach for providing C-level bindings, we should implement @@ -14,4 +15,4 @@ expected outcome: -dependencies: \ No newline at end of file +dependencies: Modified: pypy/extradoc/planning/roadmap/task_manual_optimizations.txt ============================================================================== --- pypy/extradoc/planning/roadmap/task_manual_optimizations.txt (original) +++ pypy/extradoc/planning/roadmap/task_manual_optimizations.txt Sun May 11 11:41:31 2008 @@ -5,6 +5,9 @@ - Improvements to the interpreter is an ongoing task. Some microbenchmarks show particularly bad performance in specific areas. + - Various optimizations were performed, PyPy seems to be at most two times + as slow in the microbenchmarks. Nevertheless, there are a few areas left + that could be tackled (like speeding up function calls). todo: @@ -19,4 +22,4 @@ dependencies: -- None \ No newline at end of file +- None Modified: pypy/extradoc/planning/roadmap/task_multi_platform.txt ============================================================================== --- pypy/extradoc/planning/roadmap/task_multi_platform.txt (original) +++ pypy/extradoc/planning/roadmap/task_multi_platform.txt Sun May 11 11:41:31 2008 @@ -5,10 +5,11 @@ - We currently have PyPy with Posix support running on the following platforms: + - Linux ia32 - Mac OS/X ia32 - Mac OS/X powerpc - - Windows ia32 + - Windows ia32 (only limited, a few known issues, needs a maintainer) todo: @@ -36,4 +37,4 @@ - Somebody showed up o the PyPy IRC channel with an interest in putting together a group of people doing the port to amd64. It remains to be seen if this group takes off. If so, we may have - a port earlier than expected. \ No newline at end of file + a port earlier than expected. Modified: pypy/extradoc/planning/roadmap/task_refactor_jit.txt ============================================================================== --- pypy/extradoc/planning/roadmap/task_refactor_jit.txt (original) +++ pypy/extradoc/planning/roadmap/task_refactor_jit.txt Sun May 11 11:41:31 2008 @@ -3,16 +3,16 @@ status: + - Currently underway on a few branches, refer to Carl and Armin for details. + +todo: + - The JIT is the result of programming under severe time pressure. This means that the existing JIT framework needs a fair bit of cleanup and - restructuring. Armin also has some ideas for a refactoring based on an - interpreter, rather than annotated graphs. + restructuring. - - XXX maybe phrase this a bit more clearly. - -todo: expected outcome: dependencies: - - None \ No newline at end of file + - None From fijal at codespeak.net Sun May 11 11:54:16 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 11 May 2008 11:54:16 +0200 (CEST) Subject: [pypy-svn] r54645 - pypy/branch/hybrid-io Message-ID: <20080511095416.6272F16A2B2@codespeak.net> Author: fijal Date: Sun May 11 11:54:15 2008 New Revision: 54645 Removed: pypy/branch/hybrid-io/ Log: Delete this branch, we'll branch differently From fijal at codespeak.net Sun May 11 12:10:26 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 11 May 2008 12:10:26 +0200 (CEST) Subject: [pypy-svn] r54646 - pypy/branch/io-improvements/pypy/objspace/std Message-ID: <20080511101026.888A816A2B9@codespeak.net> Author: fijal Date: Sun May 11 12:10:26 2008 New Revision: 54646 Modified: pypy/branch/io-improvements/pypy/objspace/std/stringobject.py Log: Use stringbuilder also for repr__String (xoraxax suggestion) Modified: pypy/branch/io-improvements/pypy/objspace/std/stringobject.py ============================================================================== --- pypy/branch/io-improvements/pypy/objspace/std/stringobject.py (original) +++ pypy/branch/io-improvements/pypy/objspace/std/stringobject.py Sun May 11 12:10:26 2008 @@ -10,6 +10,7 @@ from pypy.objspace.std.listobject import W_ListObject from pypy.objspace.std.noneobject import W_NoneObject from pypy.objspace.std.tupleobject import W_TupleObject +from pypy.rlib.rstring import StringBuilder from pypy.objspace.std.stringtype import sliced, joined, wrapstr, wrapchar, \ stringendswith, stringstartswith, joined2 @@ -860,17 +861,17 @@ def repr__String(space, w_str): s = w_str._value - i = 0 - buf = [' '] * (len(s) * 4 + 2) # safely overallocate + buf = StringBuilder(len(s) * 4 + 2) quote = "'" if quote in s and '"' not in s: quote = '"' - buf[i] = quote + buf.append(quote) + startslice = 0 - for c in s: - i += 1 + for i in range(len(s)): + c = s[i] use_bs_char = False # character quoted by backspace if c == '\\' or c == quote: @@ -887,25 +888,26 @@ use_bs_char = True elif not '\x20' <= c < '\x7f': n = ord(c) - buf[i] = '\\' - i += 1 - buf[i] = 'x' - i += 1 - buf[i] = "0123456789abcdef"[n>>4] - i += 1 - buf[i] = "0123456789abcdef"[n&0xF] - else: - buf[i] = c + if i != startslice: + buf.append_slice(s, startslice, i) + startslice = i + 1 + buf.append('\\x') + buf.append("0123456789abcdef"[n>>4]) + buf.append("0123456789abcdef"[n&0xF]) if use_bs_char: - buf[i] = '\\' - i += 1 - buf[i] = bs_char + if i != startslice: + buf.append_slice(s, startslice, i) + startslice = i + 1 + buf.append('\\') + buf.append(bs_char) + + if len(s) != startslice: + buf.append_slice(s, startslice, len(s)) - i += 1 - buf[i] = quote + buf.append(quote) - return space.wrap("".join(buf[:i+1])) # buffer was overallocated, so slice + return space.wrap(buf.build()) # buffer was overallocated, so slice def str_translate__String_ANY_ANY(space, w_string, w_table, w_deletechars=''): From fijal at codespeak.net Sun May 11 12:15:06 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 11 May 2008 12:15:06 +0200 (CEST) Subject: [pypy-svn] r54647 - pypy/branch/hybrid-io Message-ID: <20080511101506.A0D8A16A2B7@codespeak.net> Author: fijal Date: Sun May 11 12:15:06 2008 New Revision: 54647 Added: pypy/branch/hybrid-io/ - copied from r54646, pypy/dist/ Log: Create a branch (third time) to merge hybrid gc and io-improvements From fijal at codespeak.net Sun May 11 12:22:09 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 11 May 2008 12:22:09 +0200 (CEST) Subject: [pypy-svn] r54648 - pypy/branch/io-improvements/pypy/objspace/std Message-ID: <20080511102209.0378A16A087@codespeak.net> Author: fijal Date: Sun May 11 12:22:09 2008 New Revision: 54648 Modified: pypy/branch/io-improvements/pypy/objspace/std/stringobject.py Log: * We can safely overallocate less this time. * Kill outdated comment Modified: pypy/branch/io-improvements/pypy/objspace/std/stringobject.py ============================================================================== --- pypy/branch/io-improvements/pypy/objspace/std/stringobject.py (original) +++ pypy/branch/io-improvements/pypy/objspace/std/stringobject.py Sun May 11 12:22:09 2008 @@ -861,7 +861,7 @@ def repr__String(space, w_str): s = w_str._value - buf = StringBuilder(len(s) * 4 + 2) + buf = StringBuilder(len(s) + 10) quote = "'" if quote in s and '"' not in s: @@ -907,7 +907,7 @@ buf.append(quote) - return space.wrap(buf.build()) # buffer was overallocated, so slice + return space.wrap(buf.build()) def str_translate__String_ANY_ANY(space, w_string, w_table, w_deletechars=''): From fijal at codespeak.net Sun May 11 12:45:50 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 11 May 2008 12:45:50 +0200 (CEST) Subject: [pypy-svn] r54649 - in pypy/branch/hybrid-io/pypy: . config interpreter objspace/std rlib rlib/test rpython rpython/lltypesystem rpython/lltypesystem/test rpython/memory rpython/memory/gc rpython/memory/gctransform rpython/memory/test rpython/module rpython/module/test rpython/ootypesystem rpython/test translator translator/backendopt translator/backendopt/test translator/c translator/c/test translator/goal translator/llvm Message-ID: <20080511104550.B72412A80B3@codespeak.net> Author: fijal Date: Sun May 11 12:45:47 2008 New Revision: 54649 Added: pypy/branch/hybrid-io/pypy/FAILURES - copied unchanged from r54648, pypy/branch/io-improvements/pypy/FAILURES pypy/branch/hybrid-io/pypy/rpython/lltypesystem/rbuilder.py - copied unchanged from r54648, pypy/branch/io-improvements/pypy/rpython/lltypesystem/rbuilder.py pypy/branch/hybrid-io/pypy/rpython/ootypesystem/rbuilder.py - copied unchanged from r54648, pypy/branch/io-improvements/pypy/rpython/ootypesystem/rbuilder.py pypy/branch/hybrid-io/pypy/rpython/rbuilder.py - copied unchanged from r54648, pypy/branch/io-improvements/pypy/rpython/rbuilder.py pypy/branch/hybrid-io/pypy/rpython/test/test_rbuilder.py - copied unchanged from r54648, pypy/branch/io-improvements/pypy/rpython/test/test_rbuilder.py pypy/branch/hybrid-io/pypy/translator/goal/targetreadlines.py - copied unchanged from r54648, pypy/branch/io-improvements/pypy/translator/goal/targetreadlines.py pypy/branch/hybrid-io/pypy/translator/goal/targetsimpleread.py - copied unchanged from r54648, pypy/branch/io-improvements/pypy/translator/goal/targetsimpleread.py pypy/branch/hybrid-io/pypy/translator/goal/targetsimplewrite.py - copied unchanged from r54648, pypy/branch/io-improvements/pypy/translator/goal/targetsimplewrite.py Removed: pypy/branch/hybrid-io/pypy/translator/backendopt/coalloc.py pypy/branch/hybrid-io/pypy/translator/backendopt/test/test_coalloc.py Modified: pypy/branch/hybrid-io/pypy/config/translationoption.py pypy/branch/hybrid-io/pypy/interpreter/pyframe.py pypy/branch/hybrid-io/pypy/interpreter/pyopcode.py pypy/branch/hybrid-io/pypy/objspace/std/formatting.py pypy/branch/hybrid-io/pypy/objspace/std/stringobject.py pypy/branch/hybrid-io/pypy/rlib/rgc.py pypy/branch/hybrid-io/pypy/rlib/rsocket.py pypy/branch/hybrid-io/pypy/rlib/rstring.py pypy/branch/hybrid-io/pypy/rlib/rzlib.py pypy/branch/hybrid-io/pypy/rlib/streamio.py pypy/branch/hybrid-io/pypy/rlib/test/test_rgc.py pypy/branch/hybrid-io/pypy/rlib/test/test_rsocket.py pypy/branch/hybrid-io/pypy/rlib/test/test_rstring.py pypy/branch/hybrid-io/pypy/rpython/annlowlevel.py pypy/branch/hybrid-io/pypy/rpython/llinterp.py pypy/branch/hybrid-io/pypy/rpython/lltypesystem/ll2ctypes.py pypy/branch/hybrid-io/pypy/rpython/lltypesystem/ll_str.py pypy/branch/hybrid-io/pypy/rpython/lltypesystem/llheap.py pypy/branch/hybrid-io/pypy/rpython/lltypesystem/llmemory.py pypy/branch/hybrid-io/pypy/rpython/lltypesystem/lloperation.py pypy/branch/hybrid-io/pypy/rpython/lltypesystem/lltype.py pypy/branch/hybrid-io/pypy/rpython/lltypesystem/rffi.py pypy/branch/hybrid-io/pypy/rpython/lltypesystem/rstr.py pypy/branch/hybrid-io/pypy/rpython/lltypesystem/test/test_ll2ctypes.py pypy/branch/hybrid-io/pypy/rpython/lltypesystem/test/test_llmemory.py pypy/branch/hybrid-io/pypy/rpython/lltypesystem/test/test_lltype.py pypy/branch/hybrid-io/pypy/rpython/lltypesystem/test/test_rffi.py pypy/branch/hybrid-io/pypy/rpython/memory/gc/base.py pypy/branch/hybrid-io/pypy/rpython/memory/gc/generation.py pypy/branch/hybrid-io/pypy/rpython/memory/gctransform/boehm.py pypy/branch/hybrid-io/pypy/rpython/memory/gctransform/framework.py pypy/branch/hybrid-io/pypy/rpython/memory/gctransform/transform.py pypy/branch/hybrid-io/pypy/rpython/memory/gcwrapper.py pypy/branch/hybrid-io/pypy/rpython/memory/test/test_gc.py pypy/branch/hybrid-io/pypy/rpython/memory/test/test_transformed_gc.py pypy/branch/hybrid-io/pypy/rpython/module/ll_os.py pypy/branch/hybrid-io/pypy/rpython/module/test/test_posix.py pypy/branch/hybrid-io/pypy/rpython/rpbc.py pypy/branch/hybrid-io/pypy/rpython/test/test_annlowlevel.py pypy/branch/hybrid-io/pypy/rpython/test/test_rbuiltin.py pypy/branch/hybrid-io/pypy/rpython/test/test_rlist.py pypy/branch/hybrid-io/pypy/rpython/test/test_runicode.py pypy/branch/hybrid-io/pypy/rpython/typesystem.py pypy/branch/hybrid-io/pypy/translator/backendopt/all.py pypy/branch/hybrid-io/pypy/translator/c/funcgen.py pypy/branch/hybrid-io/pypy/translator/c/test/test_boehm.py pypy/branch/hybrid-io/pypy/translator/c/test/test_lltyped.py pypy/branch/hybrid-io/pypy/translator/c/test/test_newgc.py pypy/branch/hybrid-io/pypy/translator/exceptiontransform.py pypy/branch/hybrid-io/pypy/translator/llvm/opwriter.py Log: (fijal, arigo, docgok) svn merge -r 53620:54648 http://codespeak.net/svn/pypy/dist/pypy . Merge the io-improvements branch into hybrid-io branch. This branch approaches problem of io (and string operations) bottlenecks by introducing few gc primitives that can express better certain situations. * Implement rgc.can_move(ptr) primitive and rgc.malloc_nonmovable which respectively tells whether pointer can move and tries to allocate area that will never move. Useful for passing into C-level functions. * Use this interface to speedup os.read, os.write, rsocket.send/recv and rzlib * Various small performance improvements, including streamio readline and rstr using raw_memcopy instead of copying by hand * Implement resizable_buffer interface, which exposes three functions: rgc.resizable_buffer_of_shape, rgc.resize_buffer and rgc.finish_building_buffer * Implement rlib.rstring.StringBuilder and UnicodeBuilder, which uses resizable_buffer interface for in-place string building. * Use StringBuilder/UnicodeBuilder for modulo operation on str/unicode and for repr(str) * Implement GC_REALLOC for boehm, using rffi (which is way nicer :) * Introduce new operation FORCE_CAST, for casting between different types on top of llinterp * Remove coalloc, it speeded up things by accident Modified: pypy/branch/hybrid-io/pypy/config/translationoption.py ============================================================================== --- pypy/branch/hybrid-io/pypy/config/translationoption.py (original) +++ pypy/branch/hybrid-io/pypy/config/translationoption.py Sun May 11 12:45:47 2008 @@ -176,9 +176,6 @@ BoolOption("heap2stack", "Escape analysis and stack allocation", default=False, requires=[("translation.stackless", False)]), - BoolOption("coalloc", "Try to replace mallocs by coallocation", - default=False, - suggests=[("translation.gc", "generation")]), # control profile based inlining StrOption("profile_based_inline", "Use call count profiling to drive inlining" Modified: pypy/branch/hybrid-io/pypy/interpreter/pyframe.py ============================================================================== --- pypy/branch/hybrid-io/pypy/interpreter/pyframe.py (original) +++ pypy/branch/hybrid-io/pypy/interpreter/pyframe.py Sun May 11 12:45:47 2008 @@ -9,8 +9,6 @@ import opcode from pypy.rlib.objectmodel import we_are_translated, instantiate from pypy.rlib.jit import we_are_jitted, hint -from pypy.rlib import rstack # for resume points - # Define some opcodes used g = globals() @@ -102,6 +100,7 @@ def execute_frame(self): """Execute this frame. Main entry point to the interpreter.""" + from pypy.rlib import rstack executioncontext = self.space.getexecutioncontext() executioncontext.enter(self) try: Modified: pypy/branch/hybrid-io/pypy/interpreter/pyopcode.py ============================================================================== --- pypy/branch/hybrid-io/pypy/interpreter/pyopcode.py (original) +++ pypy/branch/hybrid-io/pypy/interpreter/pyopcode.py Sun May 11 12:45:47 2008 @@ -18,7 +18,6 @@ from pypy.tool.stdlib_opcode import opcodedesc, HAVE_ARGUMENT from pypy.tool.stdlib_opcode import unrolling_opcode_descs from pypy.tool.stdlib_opcode import opcode_method_names -from pypy.rlib import rstack # for resume points from pypy.rlib.unroll import unrolling_iterable def unaryoperation(operationname): @@ -70,6 +69,8 @@ def dispatch(self, pycode, next_instr, ec): # For the sequel, force 'next_instr' to be unsigned for performance + from pypy.rlib import rstack # for resume points + next_instr = r_uint(next_instr) co_code = pycode.co_code @@ -82,6 +83,8 @@ return self.popvalue() def handle_bytecode(self, co_code, next_instr, ec): + from pypy.rlib import rstack # for resume points + try: next_instr = self.dispatch_bytecode(co_code, next_instr, ec) rstack.resume_point("handle_bytecode", self, co_code, ec, @@ -203,6 +206,8 @@ return next_instr if we_are_translated(): + from pypy.rlib import rstack # for resume points + for opdesc in unrolling_opcode_descs: # static checks to skip this whole case if necessary if not opdesc.is_enabled(space): @@ -850,6 +855,8 @@ f.space.w_None) def call_function(f, oparg, w_star=None, w_starstar=None): + from pypy.rlib import rstack # for resume points + n_arguments = oparg & 0xff n_keywords = (oparg>>8) & 0xff keywords = None @@ -863,6 +870,8 @@ f.pushvalue(w_result) def CALL_FUNCTION(f, oparg, *ignored): + from pypy.rlib import rstack # for resume points + # XXX start of hack for performance if (oparg >> 8) & 0xff == 0: # Only positional arguments Modified: pypy/branch/hybrid-io/pypy/objspace/std/formatting.py ============================================================================== --- pypy/branch/hybrid-io/pypy/objspace/std/formatting.py (original) +++ pypy/branch/hybrid-io/pypy/objspace/std/formatting.py Sun May 11 12:45:47 2008 @@ -5,8 +5,7 @@ from pypy.rlib.rarithmetic import ovfcheck, formatd_overflow, isnan, isinf from pypy.interpreter.error import OperationError from pypy.tool.sourcetools import func_with_new_name -from pypy.rlib.debug import check_annotation -from pypy.rlib.objectmodel import newlist +from pypy.rlib.rstring import StringBuilder, UnicodeBuilder class BaseStringFormatter(object): def __init__(self, space, values_w, w_valuedict): @@ -257,7 +256,10 @@ return result def format(self): - result = newlist(sizehint=100) # list of characters or unichars + if do_unicode: + result = UnicodeBuilder() + else: + result = StringBuilder() self.result = result while True: # fast path: consume as many characters as possible @@ -268,9 +270,9 @@ break i += 1 else: - result += const(fmt[i0:]) - break # end of 'fmt' string - result += const(fmt[i0:i]) + result.append_slice(fmt, i0, len(fmt)) + break # end of 'fmt' string + result.append_slice(fmt, i0, i) self.fmtpos = i + 1 # interpret the next formatter @@ -296,7 +298,7 @@ self.unknown_fmtchar() self.checkconsumed() - return result + return result.build() def unknown_fmtchar(self): space = self.space @@ -317,22 +319,28 @@ def std_wp(self, r): length = len(r) + if do_unicode and isinstance(r, str): + # convert string to unicode explicitely here + r = unicode(r) prec = self.prec if prec == -1 and self.width == 0: # fast path - self.result += const(r) + self.result.append(const(r)) return if prec >= 0 and prec < length: length = prec # ignore the end of the string if too long result = self.result padding = self.width - length + if padding < 0: + padding = 0 + assert padding >= 0 if not self.f_ljust and padding > 0: - result += const(' ') * padding + result.append_multiple_char(const(' '), padding) # add any padding at the left of 'r' padding = 0 - result += const(r[:length]) # add 'r' itself + result.append_slice(r, 0, length) # add 'r' itself if padding > 0: - result += const(' ') * padding + result.append_multiple_char(const(' '), padding) # add any remaining padding at the right std_wp._annspecialcase_ = 'specialize:argtype(1)' @@ -351,6 +359,8 @@ # by pushing the pad character into self.result result = self.result padding = self.width - len(r) - len(prefix) + if padding <= 0: + padding = 0 if self.f_ljust: padnumber = '<' @@ -359,16 +369,20 @@ else: padnumber = '>' + assert padding >= 0 if padnumber == '>': - result += const(' ') * padding # pad with spaces on the left + result.append_multiple_char(const(' '), padding) + # pad with spaces on the left if sign: - result += const(r[0]) # the sign - result += const(prefix) # the prefix + result.append(const(r[0])) # the sign + result.append(const(prefix)) # the prefix if padnumber == '0': - result += const('0') * padding # pad with zeroes - result += const(r[int(sign):]) # the rest of the number + result.append_multiple_char(const('0'), padding) + # pad with zeroes + result.append_slice(const(r), int(sign), len(r)) + # the rest of the number if padnumber == '<': # spaces on the right - result += const(' ') * padding + result.append_multiple_char(const(' '), padding) def fmt_s(self, w_value): space = self.space @@ -455,14 +469,12 @@ # fall through to the unicode case fmt = unicode(fmt) else: - check_annotation(result, is_list_of_chars_or_unichars) - return space.wrap(''.join(result)) + return space.wrap(result) else: fmt = space.unicode_w(w_fmt) formatter = UnicodeFormatter(space, fmt, values_w, w_valuedict) result = formatter.format() - check_annotation(result, is_list_of_chars_or_unichars) - return space.wrap(u''.join(result)) + return space.wrap(result) def mod_format(space, w_format, w_values, do_unicode=False): if space.is_true(space.isinstance(w_values, space.w_tuple)): Modified: pypy/branch/hybrid-io/pypy/objspace/std/stringobject.py ============================================================================== --- pypy/branch/hybrid-io/pypy/objspace/std/stringobject.py (original) +++ pypy/branch/hybrid-io/pypy/objspace/std/stringobject.py Sun May 11 12:45:47 2008 @@ -10,6 +10,7 @@ from pypy.objspace.std.listobject import W_ListObject from pypy.objspace.std.noneobject import W_NoneObject from pypy.objspace.std.tupleobject import W_TupleObject +from pypy.rlib.rstring import StringBuilder from pypy.objspace.std.stringtype import sliced, joined, wrapstr, wrapchar, \ stringendswith, stringstartswith, joined2 @@ -860,17 +861,17 @@ def repr__String(space, w_str): s = w_str._value - i = 0 - buf = [' '] * (len(s) * 4 + 2) # safely overallocate + buf = StringBuilder(len(s) + 10) quote = "'" if quote in s and '"' not in s: quote = '"' - buf[i] = quote + buf.append(quote) + startslice = 0 - for c in s: - i += 1 + for i in range(len(s)): + c = s[i] use_bs_char = False # character quoted by backspace if c == '\\' or c == quote: @@ -887,25 +888,26 @@ use_bs_char = True elif not '\x20' <= c < '\x7f': n = ord(c) - buf[i] = '\\' - i += 1 - buf[i] = 'x' - i += 1 - buf[i] = "0123456789abcdef"[n>>4] - i += 1 - buf[i] = "0123456789abcdef"[n&0xF] - else: - buf[i] = c + if i != startslice: + buf.append_slice(s, startslice, i) + startslice = i + 1 + buf.append('\\x') + buf.append("0123456789abcdef"[n>>4]) + buf.append("0123456789abcdef"[n&0xF]) if use_bs_char: - buf[i] = '\\' - i += 1 - buf[i] = bs_char + if i != startslice: + buf.append_slice(s, startslice, i) + startslice = i + 1 + buf.append('\\') + buf.append(bs_char) + + if len(s) != startslice: + buf.append_slice(s, startslice, len(s)) - i += 1 - buf[i] = quote + buf.append(quote) - return space.wrap("".join(buf[:i+1])) # buffer was overallocated, so slice + return space.wrap(buf.build()) def str_translate__String_ANY_ANY(space, w_string, w_table, w_deletechars=''): Modified: pypy/branch/hybrid-io/pypy/rlib/rgc.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rlib/rgc.py (original) +++ pypy/branch/hybrid-io/pypy/rlib/rgc.py Sun May 11 12:45:47 2008 @@ -185,3 +185,139 @@ opname = 'gc__' + self.instance.__name__ hop.exception_cannot_occur() return hop.genop(opname, [], resulttype=hop.r_result) + +def can_move(p): + return True + +class CanMoveEntry(ExtRegistryEntry): + _about_ = can_move + + def compute_result_annotation(self, s_p): + from pypy.annotation import model as annmodel + return annmodel.SomeBool() + + def specialize_call(self, hop): + from pypy.rpython.lltypesystem import lltype + hop.exception_cannot_occur() + return hop.genop('gc_can_move', hop.args_v, resulttype=hop.r_result) + +def malloc_nonmovable(TP, n=None): + """ Allocate a non-moving buffer or return nullptr. + When running directly, will pretend that gc is always + moving (might be configurable in a future) + """ + from pypy.rpython.lltypesystem import lltype + return lltype.nullptr(TP) + +class MallocNonMovingEntry(ExtRegistryEntry): + _about_ = malloc_nonmovable + + def compute_result_annotation(self, s_TP, s_n=None): + # basically return the same as malloc + from pypy.annotation.builtin import malloc + return malloc(s_TP, s_n) + + def specialize_call(self, hop): + from pypy.rpython.lltypesystem import lltype + # XXX assume flavor and zero to be None by now + assert hop.args_s[0].is_constant() + vlist = [hop.inputarg(lltype.Void, arg=0)] + opname = 'malloc_nonmovable' + flags = {'flavor': 'gc'} + vlist.append(hop.inputconst(lltype.Void, flags)) + + if hop.nb_args == 2: + vlist.append(hop.inputarg(lltype.Signed, arg=1)) + opname += '_varsize' + + hop.exception_cannot_occur() + return hop.genop(opname, vlist, resulttype = hop.r_result.lowleveltype) + +def resizable_buffer_of_shape(T, init_size): + """ Pre-allocates structure of type T (varsized) with possibility + to reallocate it further by resize_buffer. + """ + from pypy.rpython.lltypesystem import lltype + return lltype.malloc(T, init_size) + +class ResizableBufferOfShapeEntry(ExtRegistryEntry): + _about_ = resizable_buffer_of_shape + + def compute_result_annotation(self, s_T, s_init_size): + from pypy.annotation import model as annmodel + from pypy.rpython.lltypesystem import rffi, lltype + assert s_T.is_constant() + assert isinstance(s_init_size, annmodel.SomeInteger) + T = s_T.const + # limit ourselves to structs and to a fact that var-sized element + # does not contain pointers. + assert isinstance(T, lltype.Struct) + assert isinstance(getattr(T, T._arrayfld).OF, lltype.Primitive) + return annmodel.SomePtr(lltype.Ptr(T)) + + def specialize_call(self, hop): + from pypy.rpython.lltypesystem import lltype + flags = {'flavor': 'gc'} + vlist = [hop.inputarg(lltype.Void, 0), + hop.inputconst(lltype.Void, flags), + hop.inputarg(lltype.Signed, 1)] + hop.exception_is_here() + return hop.genop('malloc_resizable_buffer', vlist, + resulttype=hop.r_result.lowleveltype) + +def resize_buffer(ptr, old_size, new_size): + """ Resize raw buffer returned by resizable_buffer_of_shape to new size + """ + from pypy.rpython.lltypesystem import lltype + T = lltype.typeOf(ptr).TO + arrayfld = T._arrayfld + arr = getattr(ptr, arrayfld) + # we don't have any realloc on top of cpython + new_ptr = lltype.malloc(T, new_size) + new_ar = getattr(new_ptr, arrayfld) + for i in range(old_size): + new_ar[i] = arr[i] + return new_ptr + +class ResizeBufferEntry(ExtRegistryEntry): + _about_ = resize_buffer + + def compute_result_annotation(self, s_ptr, s_old_size, s_new_size): + from pypy.annotation import model as annmodel + from pypy.rpython.lltypesystem import rffi + assert isinstance(s_ptr, annmodel.SomePtr) + assert isinstance(s_new_size, annmodel.SomeInteger) + assert isinstance(s_old_size, annmodel.SomeInteger) + return s_ptr + + def specialize_call(self, hop): + from pypy.rpython.lltypesystem import lltype + vlist = [hop.inputarg(hop.args_r[0], 0), + hop.inputarg(lltype.Signed, 1), + hop.inputarg(lltype.Signed, 2)] + hop.exception_is_here() + return hop.genop('resize_buffer', vlist, + resulttype=hop.r_result.lowleveltype) + +def finish_building_buffer(ptr, final_size): + """ Finish building resizable buffer returned by resizable_buffer_of_shape + """ + return ptr + +class FinishBuildingBufferEntry(ExtRegistryEntry): + _about_ = finish_building_buffer + + def compute_result_annotation(self, s_arr, s_final_size): + from pypy.annotation.model import SomePtr, s_ImpossibleValue,\ + SomeInteger + assert isinstance(s_arr, SomePtr) + assert isinstance(s_final_size, SomeInteger) + return s_arr + + def specialize_call(self, hop): + from pypy.rpython.lltypesystem import lltype + vlist = [hop.inputarg(hop.args_r[0], 0), + hop.inputarg(hop.args_r[1], 1)] + hop.exception_cannot_occur() + return hop.genop('finish_building_buffer', vlist, + resulttype=hop.r_result.lowleveltype) Modified: pypy/branch/hybrid-io/pypy/rlib/rsocket.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rlib/rsocket.py (original) +++ pypy/branch/hybrid-io/pypy/rlib/rsocket.py Sun May 11 12:45:47 2008 @@ -814,14 +814,13 @@ if timeout == 1: raise SocketTimeout elif timeout == 0: - buf = mallocbuf(buffersize) + raw_buf, gc_buf = rffi.alloc_buffer(buffersize) try: - read_bytes = _c.socketrecv(self.fd, buf, buffersize, flags) + read_bytes = _c.socketrecv(self.fd, raw_buf, buffersize, flags) if read_bytes >= 0: - assert read_bytes <= buffersize - return ''.join([buf[i] for i in range(read_bytes)]) + return rffi.str_from_buffer(raw_buf, gc_buf, buffersize, read_bytes) finally: - lltype.free(buf, flavor='raw') + rffi.keep_buffer_alive_until_here(raw_buf, gc_buf) raise self.error_handler() def recvfrom(self, buffersize, flags=0): @@ -832,11 +831,11 @@ if timeout == 1: raise SocketTimeout elif timeout == 0: - buf = mallocbuf(buffersize) + raw_buf, gc_buf = rffi.alloc_buffer(buffersize) try: address, addr_p, addrlen_p = self._addrbuf() try: - read_bytes = _c.recvfrom(self.fd, buf, buffersize, flags, + read_bytes = _c.recvfrom(self.fd, raw_buf, buffersize, flags, addr_p, addrlen_p) addrlen = rffi.cast(lltype.Signed, addrlen_p[0]) finally: @@ -847,10 +846,10 @@ address.addrlen = addrlen else: address = None - data = ''.join([buf[i] for i in range(read_bytes)]) + data = rffi.str_from_buffer(raw_buf, gc_buf, buffersize, read_bytes) return (data, address) finally: - lltype.free(buf, flavor='raw') + rffi.keep_buffer_alive_until_here(raw_buf, gc_buf) raise self.error_handler() def send_raw(self, dataptr, length, flags=0): @@ -869,18 +868,18 @@ """Send a data string to the socket. For the optional flags argument, see the Unix manual. Return the number of bytes sent; this may be less than len(data) if the network is busy.""" - dataptr = rffi.str2charp(data) + dataptr = rffi.get_nonmovingbuffer(data) try: return self.send_raw(dataptr, len(data), flags) finally: - rffi.free_charp(dataptr) + rffi.free_nonmovingbuffer(data, dataptr) def sendall(self, data, flags=0): """Send a data string to the socket. For the optional flags argument, see the Unix manual. This calls send() repeatedly until all data is sent. If an error occurs, it's impossible to tell how much data has been sent.""" - dataptr = rffi.str2charp(data) + dataptr = rffi.get_nonmovingbuffer(data) try: remaining = len(data) p = dataptr @@ -889,7 +888,7 @@ p = rffi.ptradd(p, res) remaining -= res finally: - rffi.free_charp(dataptr) + rffi.free_nonmovingbuffer(data, dataptr) def sendto(self, data, flags, address): """Like send(data, flags) but allows specifying the destination @@ -1265,7 +1264,7 @@ raise RSocketError("unknown address family") if len(packed) != srcsize: raise ValueError("packed IP wrong length for inet_ntop") - srcbuf = rffi.str2charp(packed) + srcbuf = rffi.get_nonmovingbuffer(packed) try: dstbuf = mallocbuf(dstsize) try: @@ -1276,7 +1275,7 @@ finally: lltype.free(dstbuf, flavor='raw') finally: - lltype.free(srcbuf, flavor='raw') + rffi.free_nonmovingbuffer(packed, srcbuf) def setdefaulttimeout(timeout): if timeout < 0.0: Modified: pypy/branch/hybrid-io/pypy/rlib/rstring.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rlib/rstring.py (original) +++ pypy/branch/hybrid-io/pypy/rlib/rstring.py Sun May 11 12:45:47 2008 @@ -1,30 +1,52 @@ +""" String builder interface +""" + from pypy.rpython.extregistry import ExtRegistryEntry -from pypy.annotation import model as annmodel +from pypy.rpython.annlowlevel import llhelper + +INIT_SIZE = 100 # XXX tweak + +class AbstractStringBuilder(object): + def __init__(self, init_size=INIT_SIZE): + self.l = [] -def builder(initial_space=20): - return [] + def append(self, s): + self.l.append(s) -class SomeStringBuilder(annmodel.SomeObject): - def __init__(self, initial_space=0): - self.initial_space = initial_space + def append_slice(self, s, start, end): + self.l.append(s[start:end]) - def method_append(self, s_item): - if not isinstance(s_item, annmodel.SomeString): - raise TypeError("Can only append strings or characters to string builder") - return annmodel.SomeImpossibleValue() + def append_multiple_char(self, c, times): + self.l.append(c * times) - def method_build(self): - return annmodel.SomeString() +class StringBuilder(AbstractStringBuilder): + def build(self): + return "".join(self.l) -class StringBuilderEntry(ExtRegistryEntry): - _about_ = builder +class UnicodeBuilder(AbstractStringBuilder): + def build(self): + return u''.join(self.l) - def compute_result_annotation(self, s_initial_space=None): - if s_initial_space is None: - initial_space = 0 +class BaseEntry(object): + def compute_result_annotation(self, s_init_size=None): + from pypy.rpython.rbuilder import SomeStringBuilder, SomeUnicodeBuilder + if s_init_size is not None: + assert s_init_size.is_constant() + init_size = s_init_size.const else: - assert s_initial_space.is_constant() - initial_space = s_initial_space.const - assert isinstance(initial_space, int) - return SomeStringBuilder(initial_space) + init_size = INIT_SIZE + if self.use_unicode: + return SomeUnicodeBuilder(init_size) + return SomeStringBuilder(init_size) + + def specialize_call(self, hop): + return hop.r_result.rtyper_new(hop) + +class StringBuilderEntry(BaseEntry, ExtRegistryEntry): + _about_ = StringBuilder + use_unicode = False + +class UnicodeBuilderEntry(BaseEntry, ExtRegistryEntry): + _about_ = UnicodeBuilder + use_unicode = True Modified: pypy/branch/hybrid-io/pypy/rlib/rzlib.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rlib/rzlib.py (original) +++ pypy/branch/hybrid-io/pypy/rlib/rzlib.py Sun May 11 12:45:47 2008 @@ -154,9 +154,11 @@ Compute the CRC32 checksum of the string, possibly with the given start value, and return it as a unsigned 32 bit integer. """ - bytes = rffi.str2charp(string) - checksum = _crc32(start, rffi.cast(Bytefp, bytes), len(string)) - rffi.free_charp(bytes) + bytes = rffi.get_nonmovingbuffer(string) + try: + checksum = _crc32(start, rffi.cast(Bytefp, bytes), len(string)) + finally: + rffi.free_nonmovingbuffer(string, bytes) return checksum @@ -167,9 +169,11 @@ Compute the Adler-32 checksum of the string, possibly with the given start value, and return it as a unsigned 32 bit integer. """ - bytes = rffi.str2charp(string) - checksum = _adler32(start, rffi.cast(Bytefp, bytes), len(string)) - rffi.free_charp(bytes) + bytes = rffi.get_nonmovingbuffer(string) + try: + checksum = _adler32(start, rffi.cast(Bytefp, bytes), len(string)) + finally: + rffi.free_nonmovingbuffer(string, bytes) return checksum # ____________________________________________________________ Modified: pypy/branch/hybrid-io/pypy/rlib/streamio.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rlib/streamio.py (original) +++ pypy/branch/hybrid-io/pypy/rlib/streamio.py Sun May 11 12:45:47 2008 @@ -466,14 +466,14 @@ self.buf = "" return while self.lines: - line = self.lines[0] + line = self.lines[-1] if offset <= len(line): intoffset = intmask(offset) assert intoffset >= 0 - self.lines[0] = line[intoffset:] + self.lines[-1] = line[intoffset:] return - offset -= len(self.lines[0]) - 1 - del self.lines[0] + offset -= len(self.lines[-1]) - 1 + self.lines.pop() assert not self.lines if offset <= len(self.buf): intoffset = intmask(offset) @@ -500,6 +500,7 @@ # Skip relative to EOF by reading and saving only just as # much as needed intoffset = offset2int(offset) + self.lines.reverse() data = "\n".join(self.lines + [self.buf]) total = len(data) buffers = [data] @@ -525,6 +526,7 @@ raise StreamError("whence should be 0, 1 or 2") def readall(self): + self.lines.reverse() self.lines.append(self.buf) more = ["\n".join(self.lines)] self.lines = [] @@ -543,31 +545,33 @@ assert n >= 0 if self.lines: # See if this can be satisfied from self.lines[0] - line = self.lines[0] + line = self.lines[-1] if len(line) >= n: - self.lines[0] = line[n:] + self.lines[-1] = line[n:] return line[:n] # See if this can be satisfied *without exhausting* self.lines k = 0 i = 0 - for line in self.lines: + lgt = len(self.lines) + for linenum in range(lgt-1,-1,-1): + line = self.lines[linenum] k += len(line) if k >= n: - lines = self.lines[:i] - data = self.lines[i] + lines = self.lines[linenum + 1:] + data = self.lines[linenum] cutoff = len(data) - (k-n) assert cutoff >= 0 lines.append(data[:cutoff]) - del self.lines[:i] - self.lines[0] = data[cutoff:] + del self.lines[linenum:] + self.lines.append(data[cutoff:]) return "\n".join(lines) k += 1 - i += 1 # See if this can be satisfied from self.lines plus self.buf if k + len(self.buf) >= n: lines = self.lines + lines.reverse() self.lines = [] cutoff = n - k assert cutoff >= 0 @@ -587,6 +591,7 @@ return data[:cutoff] lines = self.lines + lines.reverse() self.lines = [] lines.append(self.buf) self.buf = "" @@ -608,16 +613,39 @@ more[-1] = data[:cutoff] return "".join(more) + # read_next_bunch is generally this, version below is slightly faster + #def _read_next_bunch(self): + # self.lines = self.buf.split("\n") + # self.buf = self.lines.pop() + # self.lines.reverse() + + def _read_next_bunch(self): + numlines = self.buf.count("\n") + self.lines = [None] * numlines + last = -1 + num = numlines - 1 + while True: + start = last + 1 + assert start >= 0 + next = self.buf.find("\n", start) + if next == -1: + if last != -1: + self.buf = self.buf[start:] + break + assert next >= 0 + self.lines[num] = self.buf[start:next] + last = next + num -= 1 + def readline(self): if self.lines: - return self.lines.pop(0) + "\n" + return self.lines.pop() + "\n" # This block is needed because read() can leave self.buf # containing newlines - self.lines = self.buf.split("\n") - self.buf = self.lines.pop() + self._read_next_bunch() if self.lines: - return self.lines.pop(0) + "\n" + return self.lines.pop() + "\n" if self.buf: buf = [self.buf] @@ -625,10 +653,9 @@ buf = [] while 1: self.buf = self.do_read(self.bufsize) - self.lines = self.buf.split("\n") - self.buf = self.lines.pop() + self._read_next_bunch() if self.lines: - buf.append(self.lines.pop(0)) + buf.append(self.lines.pop()) buf.append("\n") break if not self.buf: @@ -639,7 +666,7 @@ def peek(self): if self.lines: - return self.lines[0] + "\n" + return self.lines[-1] + "\n" else: return self.buf Modified: pypy/branch/hybrid-io/pypy/rlib/test/test_rgc.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rlib/test/test_rgc.py (original) +++ pypy/branch/hybrid-io/pypy/rlib/test/test_rgc.py Sun May 11 12:45:47 2008 @@ -1,6 +1,8 @@ from pypy.rpython.test.test_llinterp import gengraph, interpret +from pypy.rpython.lltypesystem import lltype from pypy.rlib import rgc # Force registration of gc.collect import gc +import py def test_collect(): def f(): @@ -17,3 +19,33 @@ assert res is None +def test_can_move(): + T0 = lltype.GcStruct('T') + T1 = lltype.GcArray(lltype.Float) + def f(i): + if i: + return rgc.can_move(lltype.malloc(T0)) + else: + return rgc.can_move(lltype.malloc(T1, 1)) + + t, typer, graph = gengraph(f, [int]) + ops = list(graph.iterblockops()) + res = [op for op in ops if op[1].opname == 'gc_can_move'] + assert len(res) == 2 + + res = interpret(f, [1]) + + assert res == True + +def test_resizable_buffer(): + from pypy.rpython.lltypesystem.rstr import STR + from pypy.rpython.annlowlevel import hlstr + + def f(): + ptr = rgc.resizable_buffer_of_shape(STR, 1) + ptr.chars[0] = 'a' + ptr = rgc.resize_buffer(ptr, 1, 2) + ptr.chars[1] = 'b' + return hlstr(rgc.finish_building_buffer(ptr, 2)) + + assert f() == 'ab' Modified: pypy/branch/hybrid-io/pypy/rlib/test/test_rsocket.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rlib/test/test_rsocket.py (original) +++ pypy/branch/hybrid-io/pypy/rlib/test/test_rsocket.py Sun May 11 12:45:47 2008 @@ -1,6 +1,7 @@ import py, errno, sys from pypy.rlib import rsocket from pypy.rlib.rsocket import * +from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin import socket as cpy_socket # cannot test error codes in Win32 because ll2ctypes doesn't save @@ -268,12 +269,12 @@ def test_getaddrinfo_no_reverse_lookup(): # It seems that getaddrinfo never runs a reverse lookup on Linux. # Python2.3 on Windows returns the hostname. - lst = getaddrinfo('134.99.112.214', None, flags=AI_NUMERICHOST) + lst = getaddrinfo('213.239.226.252', None, flags=AI_NUMERICHOST) assert isinstance(lst, list) found = False for family, socktype, protocol, canonname, addr in lst: - assert canonname != 'snake.cs.uni-duesseldorf.de' - if addr.get_host() == '134.99.112.214': + assert canonname != 'codespeak.net' + if addr.get_host() == '213.239.226.252': found = True assert found, lst @@ -370,7 +371,6 @@ clientsock.close() s.close() - class TestTCP: PORT = 50007 HOST = 'localhost' Modified: pypy/branch/hybrid-io/pypy/rlib/test/test_rstring.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rlib/test/test_rstring.py (original) +++ pypy/branch/hybrid-io/pypy/rlib/test/test_rstring.py Sun May 11 12:45:47 2008 @@ -1,27 +1,20 @@ -from pypy.translator.translator import TranslationContext -from pypy.rlib import rstring -from pypy.annotation import model as annmodel +from pypy.rlib.rstring import StringBuilder, UnicodeBuilder -class TestAnnotationStringBuilder: - def annotate(self, func, args): - t = TranslationContext() - res = t.buildannotator().build_types(func, args) - return t, res +def test_string_builder(): + s = StringBuilder() + s.append("a") + s.append("abc") + s.append("a") + s.append_slice("abc", 1, 2) + s.append_multiple_char('d', 4) + assert s.build() == "aabcabdddd" - def test_builder(self): - def f(): - return rstring.builder() - - t, res = self.annotate(f, []) - assert isinstance(res, rstring.SomeStringBuilder) - - def test_methods(self): - def f(x): - b = rstring.builder() - for i in range(x): - b.append("abc") - return b.build() - - t, res = self.annotate(f, [int]) - assert isinstance(res, annmodel.SomeString) +def test_unicode_builder(): + s = UnicodeBuilder() + s.append(u'a') + s.append(u'abc') + s.append_slice(u'abcdef', 1, 2) + s.append_multiple_char('d', 4) + assert s.build() == 'aabcbdddd' + assert isinstance(s.build(), unicode) Modified: pypy/branch/hybrid-io/pypy/rpython/annlowlevel.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/annlowlevel.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/annlowlevel.py Sun May 11 12:45:47 2008 @@ -400,6 +400,28 @@ return hop.genop('same_as', [v_ll_str], resulttype = hop.r_result.lowleveltype) +def llstr(s): + from pypy.rpython.lltypesystem.rstr import mallocstr + # XXX not sure what to do with ootypesystem + ll_s = mallocstr(len(s)) + for i, c in enumerate(s): + ll_s.chars[i] = c + return ll_s + +class LLStrEntry(extregistry.ExtRegistryEntry): + _about_ = llstr + + def compute_result_annotation(self, s_str): + from pypy.rpython.lltypesystem.rstr import STR + return annmodel.lltype_to_annotation(lltype.Ptr(STR)) + + def specialize_call(self, hop): + hop.exception_cannot_occur() + assert hop.args_r[0].lowleveltype == hop.r_result.lowleveltype + v_ll_str, = hop.inputargs(*hop.args_r) + return hop.genop('same_as', [v_ll_str], + resulttype = hop.r_result.lowleveltype) + # ____________________________________________________________ def cast_object_to_ptr(PTR, object): Modified: pypy/branch/hybrid-io/pypy/rpython/llinterp.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/llinterp.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/llinterp.py Sun May 11 12:45:47 2008 @@ -673,13 +673,6 @@ self.llinterpreter.remember_malloc(ptr, self) return ptr - def op_coalloc(self, obj, coallocator, flags): - flavor = flags['flavor'] - assert flavor == "gc" - zero = flags.get('zero', False) - ptr = self.heap.coalloc(obj, coallocator, zero=zero) - return ptr - def op_malloc_varsize(self, obj, flags, size): flavor = flags['flavor'] zero = flags.get('zero', False) @@ -691,14 +684,27 @@ return ptr except MemoryError: self.make_llexception() - - def op_coalloc_varsize(self, obj, coallocator, flags, size): + + def op_malloc_nonmovable(self, obj, flags): flavor = flags['flavor'] + assert flavor == 'gc' zero = flags.get('zero', False) - assert flavor == "gc" + return self.heap.malloc_nonmovable(obj, zero=zero) + + def op_malloc_nonmovable_varsize(self, obj, flags, size): + flavor = flags['flavor'] + assert flavor == 'gc' zero = flags.get('zero', False) - ptr = self.heap.coalloc(obj, coallocator, size, zero=zero) - return ptr + return self.heap.malloc_nonmovable(obj, size, zero=zero) + + def op_malloc_resizable_buffer(self, obj, flags, size): + return self.heap.malloc_resizable_buffer(obj, size) + + def op_resize_buffer(self, obj, old_size, new_size): + return self.heap.resize_buffer(obj, old_size, new_size) + + def op_finish_building_buffer(self, obj, size): + return self.heap.finish_building_buffer(obj, size) def op_free(self, obj, flavor): assert isinstance(flavor, str) @@ -716,6 +722,11 @@ lltype.ContainerType) return getattr(obj, field) + def op_force_cast(self, RESTYPE, obj): + from pypy.rpython.lltypesystem import ll2ctypes + return ll2ctypes.force_cast(RESTYPE, obj) + op_force_cast.need_result_type = True + def op_cast_int_to_ptr(self, RESTYPE, int1): return lltype.cast_int_to_ptr(RESTYPE, int1) op_cast_int_to_ptr.need_result_type = True @@ -759,6 +770,9 @@ def op_gc__enable_finalizers(self): self.heap.enable_finalizers() + def op_gc_can_move(self, addr): + return self.heap.can_move(addr) + def op_gc_free(self, addr): # what can you do? pass Modified: pypy/branch/hybrid-io/pypy/rpython/lltypesystem/ll2ctypes.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/lltypesystem/ll2ctypes.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/lltypesystem/ll2ctypes.py Sun May 11 12:45:47 2008 @@ -204,7 +204,11 @@ return # regular case: allocate a new ctypes Structure of the proper type cls = get_ctypes_type(STRUCT) - cstruct = cls._malloc() + if STRUCT._arrayfld: + n = len(getattr(container, STRUCT._arrayfld).items) + else: + n = None + cstruct = cls._malloc(n) add_storage(container, _struct_mixin, cstruct) for field_name in STRUCT._names: FIELDTYPE = getattr(STRUCT, field_name) @@ -218,7 +222,9 @@ csubstruct = getattr(cstruct, field_name) convert_struct(field_value, csubstruct) else: - raise NotImplementedError('inlined field', FIELDTYPE) + csubarray = getattr(cstruct, field_name) + convert_array(field_value, csubarray) + #raise NotImplementedError('inlined field', FIELDTYPE) remove_regular_struct_content(container) def remove_regular_struct_content(container): @@ -228,15 +234,19 @@ if not isinstance(FIELDTYPE, lltype.ContainerType): delattr(container, field_name) -def convert_array(container): +def convert_array(container, carray=None): ARRAY = container._TYPE cls = get_ctypes_type(ARRAY) - carray = cls._malloc(container.getlength()) + if carray is None: + carray = cls._malloc(container.getlength()) add_storage(container, _array_mixin, carray) if not isinstance(ARRAY.OF, lltype.ContainerType): + # fish that we have enough space + ctypes_array = ctypes.cast(carray.items, + ctypes.POINTER(carray.items._type_)) for i in range(container.getlength()): item_value = container.items[i] # fish fish - carray.items[i] = lltype2ctypes(item_value) + ctypes_array[i] = lltype2ctypes(item_value) remove_regular_array_content(container) else: assert isinstance(ARRAY.OF, lltype.Struct) @@ -255,7 +265,10 @@ remove_regular_struct_content(container) for field_name in STRUCT._names: FIELDTYPE = getattr(STRUCT, field_name) - if isinstance(FIELDTYPE, lltype.ContainerType): + if isinstance(FIELDTYPE, lltype.Array): + convert_array(getattr(container, field_name), + getattr(ctypes_storage, field_name)) + elif isinstance(FIELDTYPE, lltype.ContainerType): struct_use_ctypes_storage(getattr(container, field_name), getattr(ctypes_storage, field_name)) @@ -375,6 +388,22 @@ # ____________________________________________________________ +def _find_parent(llobj): + parent, parentindex = lltype.parentlink(llobj) + if parent is None: + return llobj, 0 + next_p, next_i = _find_parent(parent) + if isinstance(parentindex, int): + c_tp = get_ctypes_type(lltype.typeOf(parent)) + sizeof = ctypes.sizeof(get_ctypes_type(lltype.typeOf(parent).OF)) + ofs = c_tp.items.offset + parentindex * sizeof + return next_p, next_i + ofs + else: + c_tp = get_ctypes_type(lltype.typeOf(parent)) + ofs = getattr(c_tp, parentindex).offset + return next_p, next_i + ofs + + # XXX THIS IS A HACK XXX # ctypes does not keep callback arguments alive. So we do. Forever # we need to think deeper how to approach this problem @@ -418,6 +447,11 @@ if T.TO._gckind != 'raw' and not T.TO._hints.get('callback', None): raise Exception("can only pass 'raw' data structures to C, not %r" % (T.TO._gckind,)) + + index = 0 + if isinstance(container, lltype._subarray): + topmost, index = _find_parent(container) + container = topmost if container._storage is None: raise RuntimeError("attempting to pass a freed structure to C") if container._storage is True: @@ -434,7 +468,17 @@ container._ctypes_storage_was_allocated() storage = container._storage p = ctypes.pointer(storage) - if normalize and hasattr(storage, '_normalized_ctype'): + if index: + p = ctypes.cast(p, ctypes.c_void_p) + p = ctypes.c_void_p(p.value + index) + c_tp = get_ctypes_type(T.TO) + storage._normalized_ctype = c_tp + if normalize and getattr(T.TO, '_arrayfld', None): + # XXX doesn't cache + c_tp = build_ctypes_struct(T.TO, [], + len(getattr(storage, T.TO._arrayfld).items)) + p = ctypes.cast(p, ctypes.POINTER(c_tp)) + elif normalize and hasattr(storage, '_normalized_ctype'): p = ctypes.cast(p, ctypes.POINTER(storage._normalized_ctype)) return p @@ -449,7 +493,6 @@ if T is lltype.SingleFloat: return ctypes.c_float(float(llobj)) - return llobj def ctypes2lltype(T, cobj): @@ -461,8 +504,10 @@ return lltype.nullptr(T.TO) if isinstance(T.TO, lltype.Struct): if T.TO._arrayfld is not None: - raise NotImplementedError("XXX var-sized structs") - container = lltype._struct(T.TO) + lgt = getattr(cobj.contents, T.TO._arrayfld).length + container = lltype._struct(T.TO, lgt) + else: + container = lltype._struct(T.TO) struct_use_ctypes_storage(container, cobj.contents) elif isinstance(T.TO, lltype.Array): if T.TO._hints.get('nolength', False): @@ -630,6 +675,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.fakeaddress): + value = value.ptr TYPE1 = lltype.typeOf(value) cvalue = lltype2ctypes(value) cresulttype = get_ctypes_type(RESTYPE) @@ -665,14 +712,12 @@ return annmodel.lltype_to_annotation(RESTYPE) def specialize_call(self, hop): - from pypy.rpython.rbuiltin import gen_cast hop.exception_cannot_occur() s_RESTYPE = hop.args_s[0] assert s_RESTYPE.is_constant() RESTYPE = s_RESTYPE.const v_arg = hop.inputarg(hop.args_r[1], arg=1) - TYPE1 = v_arg.concretetype - return gen_cast(hop.llops, RESTYPE, v_arg) + return hop.genop('force_cast', [v_arg], resulttype = RESTYPE) def typecheck_ptradd(T): # --- ptradd() is only for pointers to non-GC, no-length arrays. Modified: pypy/branch/hybrid-io/pypy/rpython/lltypesystem/ll_str.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/lltypesystem/ll_str.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/lltypesystem/ll_str.py Sun May 11 12:45:47 2008 @@ -1,4 +1,5 @@ from pypy.rpython.lltypesystem.lltype import GcArray, Array, Char, malloc +from pypy.rpython.annlowlevel import llstr from pypy.rlib.rarithmetic import r_uint, formatd CHAR_ARRAY = GcArray(Char) @@ -115,5 +116,5 @@ return result def ll_float_str(repr, f): - return formatd("%f", f) + return llstr(formatd("%f", f)) Modified: pypy/branch/hybrid-io/pypy/rpython/lltypesystem/llheap.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/lltypesystem/llheap.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/lltypesystem/llheap.py Sun May 11 12:45:47 2008 @@ -6,6 +6,7 @@ setfield = setattr from operator import setitem as setarrayitem from pypy.rlib.rgc import collect, disable_finalizers, enable_finalizers +from pypy.rlib.rgc import can_move def setinterior(toplevelcontainer, inneraddr, INNERTYPE, newvalue): assert typeOf(newvalue) == INNERTYPE @@ -17,6 +18,19 @@ def weakref_create_getlazy(objgetter): return weakref_create(objgetter()) -def coalloc(T, coallocator, n=None, zero=True): - # ignore the coallocator - return malloc(T, n, zero=zero) +malloc_nonmovable = malloc + +def malloc_resizable_buffer(TP, size): + return malloc(TP, size) + +def resize_buffer(buf, old_size, new_size): + ll_str = malloc(typeOf(buf).TO, new_size) + for i in range(old_size): + ll_str.chars[i] = buf.chars[i] + return ll_str + +def finish_building_buffer(buf, final_size): + ll_str = malloc(typeOf(buf).TO, final_size) + for i in range(final_size): + ll_str.chars[i] = buf.chars[i] + return ll_str Modified: pypy/branch/hybrid-io/pypy/rpython/lltypesystem/llmemory.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/lltypesystem/llmemory.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/lltypesystem/llmemory.py Sun May 11 12:45:47 2008 @@ -256,6 +256,7 @@ assert array_type_match(lltype.typeOf(arrayptr).TO, self.TYPE) if isinstance(self.TYPE.OF, lltype.ContainerType): # XXX this doesn't support empty arrays + # XXX it's also missing 'solid' support, probably o = arrayptr._obj.getitem(0) return o._as_ptr() else: Modified: pypy/branch/hybrid-io/pypy/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/lltypesystem/lloperation.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/lltypesystem/lloperation.py Sun May 11 12:45:47 2008 @@ -317,13 +317,17 @@ 'cast_float_to_uint': LLOp(canfold=True), # XXX need OverflowError? 'cast_float_to_longlong':LLOp(canfold=True), 'truncate_longlong_to_int':LLOp(canfold=True), + 'force_cast': LLOp(sideeffects=False), # only for rffi.cast() # __________ pointer operations __________ 'malloc': LLOp(canraise=(MemoryError,), canunwindgc=True), 'malloc_varsize': LLOp(canraise=(MemoryError,), canunwindgc=True), - 'coalloc': LLOp(canraise=(MemoryError,), canunwindgc=True), - 'coalloc_varsize': LLOp(canraise=(MemoryError,), canunwindgc=True), + 'malloc_nonmovable': LLOp(canraise=(MemoryError,), canunwindgc=True), + 'malloc_nonmovable_varsize':LLOp(canraise=(MemoryError,),canunwindgc=True), + 'malloc_resizable_buffer': LLOp(canraise=(MemoryError,),canunwindgc=True), + 'resize_buffer': LLOp(canraise=(MemoryError,),canunwindgc=True), + 'finish_building_buffer' : LLOp(), 'zero_gc_pointers_inside': LLOp(), 'free': LLOp(), 'getfield': LLOp(sideeffects=False, canrun=True), @@ -399,6 +403,7 @@ 'gc_reload_possibly_moved': LLOp(), 'gc_id': LLOp(canraise=(MemoryError,), sideeffects=False), 'gc_set_max_heap_size': LLOp(), + 'gc_can_move' : LLOp(sideeffects=False), # experimental operations in support of thread cloning, only # implemented by the Mark&Sweep GC 'gc_x_swap_pool': LLOp(canraise=(MemoryError,), canunwindgc=True), Modified: pypy/branch/hybrid-io/pypy/rpython/lltypesystem/lltype.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/lltypesystem/lltype.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/lltypesystem/lltype.py Sun May 11 12:45:47 2008 @@ -1514,9 +1514,16 @@ def __init__(self, TYPE, parent, baseoffset_or_fieldname): _parentable.__init__(self, TYPE) self._setparentstructure(parent, baseoffset_or_fieldname) + # Keep the parent array alive, we share the same allocation. + # Don't do it if we are inside a GC object, though -- it's someone + # else's job to keep the GC object alive + if typeOf(top_container(parent))._gckind == 'raw': + self._keepparent = parent def __repr__(self): - + parent = self._wrparent() + if parent is None: + return '<_subarray at %s in already freed>' % (self._parent_index,) return '<_subarray at %r in %r>' % (self._parent_index, self._parentstructure(check=False)) Modified: pypy/branch/hybrid-io/pypy/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/lltypesystem/rffi.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/lltypesystem/rffi.py Sun May 11 12:45:47 2008 @@ -2,17 +2,23 @@ from pypy.annotation import model as annmodel 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.annotation.model import lltype_to_annotation from pypy.tool.sourcetools import func_with_new_name from pypy.rlib.objectmodel import Symbolic, CDefinedIntSymbolic -from pypy.rlib import rarithmetic +from pypy.rlib.objectmodel import keepalive_until_here +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.translator.backendopt.canraise import RaiseAnalyzer -from pypy.rpython.annlowlevel import llhelper +from pypy.rpython.annlowlevel import llhelper, llstr, hlstr +from pypy.rpython.lltypesystem.rstr import STR +from pypy.rlib.objectmodel import we_are_translated +from pypy.rpython.lltypesystem import llmemory import os class UnhandledRPythonException(Exception): @@ -467,6 +473,95 @@ l.append(cp[i]) i += 1 return "".join(l) + +# str -> char* +def get_nonmovingbuffer(data): + """ + Either returns a non-moving copy or performs neccessary pointer arithmetic + to return a pointer to the characters of a string if the string is already + nonmovable. + Must be followed by a free_nonmovingbuffer call. + """ + if rgc.can_move(data): + count = len(data) + buf = lltype.malloc(CCHARP.TO, count, flavor='raw') + for i in range(count): + buf[i] = data[i] + return buf + else: + data_start = cast_ptr_to_adr(llstr(data)) + \ + offsetof(STR, 'chars') + itemoffsetof(STR.chars, 0) + return cast(CCHARP, data_start) + +# (str, char*) -> None +def free_nonmovingbuffer(data, buf): + """ + Either free a non-moving buffer or keep the original storage alive. + """ + if rgc.can_move(data): + lltype.free(buf, flavor='raw') + else: + keepalive_until_here(data) + +# int -> (char*, str) +def alloc_buffer(count): + """ + Returns a (raw_buffer, gc_buffer) pair, allocated with count bytes. + The raw_buffer can be safely passed to a native function which expects it + to not move. Call str_from_buffer with the returned values to get a safe + high-level string. When the garbage collector cooperates, this allows for + the process to be performed without an extra copy. + Make sure to call keep_buffer_alive_until_here on the returned values. + """ + str_chars_offset = offsetof(STR, 'chars') + itemoffsetof(STR.chars, 0) + gc_buf = rgc.malloc_nonmovable(STR, count) + if gc_buf: + realbuf = cast_ptr_to_adr(gc_buf) + str_chars_offset + raw_buf = cast(CCHARP, realbuf) + return raw_buf, gc_buf + else: + raw_buf = lltype.malloc(CCHARP.TO, count, flavor='raw') + return raw_buf, lltype.nullptr(STR) +alloc_buffer._always_inline_ = True # to get rid of the returned tuple obj + +# (char*, str, int, int) -> None +def str_from_buffer(raw_buf, gc_buf, allocated_size, needed_size): + """ + Converts from a pair returned by alloc_buffer to a high-level string. + The returned string will be truncated to needed_size. + """ + assert allocated_size >= needed_size + + if gc_buf and (allocated_size == needed_size): + return hlstr(gc_buf) + + new_buf = lltype.malloc(STR, needed_size) + try: + str_chars_offset = offsetof(STR, 'chars') + itemoffsetof(STR.chars, 0) + if gc_buf: + src = cast_ptr_to_adr(gc_buf) + str_chars_offset + else: + src = cast_ptr_to_adr(raw_buf) + dest = cast_ptr_to_adr(new_buf) + str_chars_offset + ## FIXME: This is bad, because dest could potentially move + ## if there are threads involved. + raw_memcopy(src, dest, + llmemory.sizeof(lltype.Char) * needed_size) + return hlstr(new_buf) + finally: + keepalive_until_here(new_buf) + +# (char*, str) -> None +def keep_buffer_alive_until_here(raw_buf, gc_buf): + """ + Keeps buffers alive or frees temporary buffers created by alloc_buffer. + This must be called after a call to alloc_buffer, usually in a try/finally + block. + """ + if gc_buf: + keepalive_until_here(gc_buf) + elif raw_buf: + lltype.free(raw_buf, flavor='raw') # char* -> str, with an upper bound on the length in case there is no \x00 def charp2strn(cp, maxlen): Modified: pypy/branch/hybrid-io/pypy/rpython/lltypesystem/rstr.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/lltypesystem/rstr.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/lltypesystem/rstr.py Sun May 11 12:45:47 2008 @@ -15,6 +15,8 @@ Bool, Void, GcArray, nullptr, pyobjectptr, cast_primitive, typeOf,\ staticAdtMethod, GcForwardReference from pypy.rpython.rmodel import Repr +from pypy.rpython.lltypesystem import llmemory +from pypy.tool.sourcetools import func_with_new_name # ____________________________________________________________ # @@ -28,7 +30,7 @@ STR = GcForwardReference() UNICODE = GcForwardReference() -def new_malloc(TP): +def new_malloc(TP, name): def mallocstr(length): ll_assert(length >= 0, "negative string length") r = malloc(TP, length) @@ -36,10 +38,10 @@ r.hash = 0 return r mallocstr._annspecialcase_ = 'specialize:semierased' - return mallocstr + return func_with_new_name(mallocstr, name) -mallocstr = new_malloc(STR) -mallocunicode = new_malloc(UNICODE) +mallocstr = new_malloc(STR, 'mallocstr') +mallocunicode = new_malloc(UNICODE, 'mallocunicode') def emptystrfun(): return emptystr @@ -47,14 +49,35 @@ def emptyunicodefun(): return emptyunicode +def _new_copy_contents_fun(TP, CHAR_TP, name): + def _str_ofs(item): + return (llmemory.offsetof(TP, 'chars') + + llmemory.itemoffsetof(TP.chars, 0) + + llmemory.sizeof(CHAR_TP) * item) + + def copy_string_contents(s1, s2, s1start, s2start, lgt): + assert s1start >= 0 + assert s2start >= 0 + assert lgt >= 0 + src = llmemory.cast_ptr_to_adr(s1) + _str_ofs(s1start) + dest = llmemory.cast_ptr_to_adr(s2) + _str_ofs(s2start) + llmemory.raw_memcopy(src, dest, llmemory.sizeof(CHAR_TP) * lgt) + copy_string_contents._always_inline_ = True + return func_with_new_name(copy_string_contents, 'copy_%s_contents' % name) + +copy_string_contents = _new_copy_contents_fun(STR, Char, 'string') +copy_unicode_contents = _new_copy_contents_fun(UNICODE, UniChar, 'unicode') + STR.become(GcStruct('rpy_string', ('hash', Signed), ('chars', Array(Char, hints={'immutable': True})), adtmeths={'malloc' : staticAdtMethod(mallocstr), - 'empty' : staticAdtMethod(emptystrfun)})) + 'empty' : staticAdtMethod(emptystrfun), + 'copy_contents' : staticAdtMethod(copy_string_contents)})) UNICODE.become(GcStruct('rpy_unicode', ('hash', Signed), ('chars', Array(UniChar, hints={'immutable': True})), adtmeths={'malloc' : staticAdtMethod(mallocunicode), - 'empty' : staticAdtMethod(emptyunicodefun)} + 'empty' : staticAdtMethod(emptyunicodefun), + 'copy_contents' : staticAdtMethod(copy_unicode_contents)} )) SIGNED_ARRAY = GcArray(Signed) CONST_STR_CACHE = WeakValueDictionary() @@ -217,6 +240,7 @@ times = 0 newstr = malloc(times) j = 0 + # XXX we can use memset here, not sure how useful this is while j < times: newstr.chars[j] = ch j += 1 @@ -268,15 +292,8 @@ len1 = len(s1.chars) len2 = len(s2.chars) newstr = s1.malloc(len1 + len2) - j = 0 - while j < len1: - newstr.chars[j] = s1.chars[j] - j += 1 - i = 0 - while i < len2: - newstr.chars[j] = s2.chars[i] - i += 1 - j += 1 + s1.copy_contents(s1, newstr, 0, 0, len1) + s1.copy_contents(s2, newstr, 0, len1, len2) return newstr def ll_strip(s, ch, left, right): @@ -293,12 +310,7 @@ rpos -= 1 r_len = rpos - lpos + 1 result = s.malloc(r_len) - i = 0 - j = lpos - while i < r_len: - result.chars[i] = s.chars[j] - i += 1 - j += 1 + s.copy_contents(s, result, lpos, 0, r_len) return result def ll_upper(s): @@ -307,7 +319,8 @@ if s_len == 0: return s.empty() i = 0 - result = s.malloc(s_len) + result = mallocstr(s_len) + # ^^^^^^^^^ specifically to explode on unicode while i < s_len: ch = s_chars[i] if 'a' <= ch <= 'z': @@ -322,7 +335,8 @@ if s_len == 0: return s.empty() i = 0 - result = s.malloc(s_len) + result = mallocstr(s_len) + # ^^^^^^^^^ specifically to explode on unicode while i < s_len: ch = s_chars[i] if 'A' <= ch <= 'Z': @@ -343,31 +357,15 @@ itemslen += len(items[i].chars) i += 1 result = s.malloc(itemslen + s_len * (num_items - 1)) - res_chars = result.chars - res_index = 0 - i = 0 - item_chars = items[i].chars - item_len = len(item_chars) - j = 0 - while j < item_len: - res_chars[res_index] = item_chars[j] - j += 1 - res_index += 1 - i += 1 + res_index = len(items[0].chars) + s.copy_contents(items[0], result, 0, 0, res_index) + i = 1 while i < num_items: - j = 0 - while j < s_len: - res_chars[res_index] = s_chars[j] - j += 1 - res_index += 1 - - item_chars = items[i].chars - item_len = len(item_chars) - j = 0 - while j < item_len: - res_chars[res_index] = item_chars[j] - j += 1 - res_index += 1 + s.copy_contents(s, result, 0, res_index, s_len) + res_index += s_len + lgt = len(items[i].chars) + s.copy_contents(items[i], result, 0, res_index, lgt) + res_index += lgt i += 1 return result @@ -599,8 +597,10 @@ i += 1 if typeOf(items).TO.OF.TO == STR: malloc = mallocstr + copy_contents = copy_string_contents else: malloc = mallocunicode + copy_contents = copy_unicode_contents result = malloc(itemslen) res_chars = result.chars res_index = 0 @@ -608,15 +608,14 @@ while i < num_items: item_chars = items[i].chars item_len = len(item_chars) - j = 0 - while j < item_len: - res_chars[res_index] = item_chars[j] - j += 1 - res_index += 1 + copy_contents(items[i], result, 0, res_index, item_len) + res_index += item_len i += 1 return result def ll_join_chars(length, chars): + # no need to optimize this, will be replaced by string builder + # at some point soon num_chars = length if typeOf(chars).TO.OF == Char: malloc = mallocstr @@ -633,11 +632,10 @@ def ll_stringslice_startonly(s1, start): len1 = len(s1.chars) newstr = s1.malloc(len1 - start) - j = 0 - while start < len1: - newstr.chars[j] = s1.chars[start] - start += 1 - j += 1 + lgt = len1 - start + assert lgt >= 0 + assert start >= 0 + s1.copy_contents(s1, newstr, start, 0, lgt) return newstr def ll_stringslice(s1, slice): @@ -648,20 +646,17 @@ return s1 stop = len(s1.chars) newstr = s1.malloc(stop - start) - j = 0 - while start < stop: - newstr.chars[j] = s1.chars[start] - start += 1 - j += 1 + assert start >= 0 + lgt = stop - start + assert lgt >= 0 + s1.copy_contents(s1, newstr, start, 0, lgt) return newstr def ll_stringslice_minusone(s1): newlen = len(s1.chars) - 1 newstr = s1.malloc(newlen) - j = 0 - while j < newlen: - newstr.chars[j] = s1.chars[j] - j += 1 + assert newlen >= 0 + s1.copy_contents(s1, newstr, 0, 0, newlen) return newstr def ll_split_chr(LIST, s, c): @@ -681,22 +676,12 @@ while j < strlen: if chars[j] == c: item = items[resindex] = s.malloc(j - i) - newchars = item.chars - k = i - while k < j: - newchars[k - i] = chars[k] - k += 1 + item.copy_contents(s, item, i, 0, j - i) resindex += 1 i = j + 1 j += 1 item = items[resindex] = s.malloc(j - i) - newchars = item.chars - k = i - while k < j: - newchars[k - i] = chars[k] - k += 1 - resindex += 1 - + item.copy_contents(s, item, i, 0, j - i) return res def ll_replace_chr_chr(s, c1, c2): Modified: pypy/branch/hybrid-io/pypy/rpython/lltypesystem/test/test_ll2ctypes.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/lltypesystem/test/test_ll2ctypes.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/lltypesystem/test/test_ll2ctypes.py Sun May 11 12:45:47 2008 @@ -6,11 +6,12 @@ from pypy.rpython.lltypesystem.ll2ctypes import lltype2ctypes, ctypes2lltype from pypy.rpython.lltypesystem.ll2ctypes import standard_c_lib from pypy.rpython.lltypesystem.ll2ctypes import uninitialized2ctypes -from pypy.rpython.lltypesystem.ll2ctypes import ALLOCATED +from pypy.rpython.lltypesystem.ll2ctypes import ALLOCATED, force_cast from pypy.rpython.annlowlevel import llhelper from pypy.rlib import rposix from pypy.translator.tool.cbuild import ExternalCompilationInfo from pypy.tool.udir import udir +from pypy.rpython.test.test_llinterp import interpret class TestLL2Ctypes(object): @@ -109,6 +110,19 @@ lltype.free(a, flavor='raw') assert not ALLOCATED # detects memory leaks in the test + def test_array_inside_struct(self): + # like rstr.STR, but not Gc + STR = lltype.Struct('STR', ('x', lltype.Signed), ('y', lltype.Array(lltype.Char))) + a = lltype.malloc(STR, 3, flavor='raw') + a.y[0] = 'x' + a.y[1] = 'y' + a.y[2] = 'z' + ac = lltype2ctypes(a) + assert ac.contents.y.length == 3 + assert ac.contents.y.items[2] == ord('z') + lltype.free(a, flavor='raw') + assert not ALLOCATED + def test_array_nolength(self): A = lltype.Array(lltype.Signed, hints={'nolength': True}) a = lltype.malloc(A, 10, flavor='raw') @@ -357,6 +371,20 @@ lltype.free(a, flavor='raw') assert not ALLOCATED # detects memory leaks in the test + def test_adr_cast(self): + from pypy.rpython.annlowlevel import llstr + from pypy.rpython.lltypesystem.rstr import STR + P = lltype.Ptr(lltype.FixedSizeArray(lltype.Char, 1)) + def f(): + a = llstr("xyz") + b = (llmemory.cast_ptr_to_adr(a) + llmemory.offsetof(STR, 'chars') + + llmemory.itemoffsetof(STR.chars, 0)) + buf = rffi.cast(rffi.VOIDP, b) + return buf[2] + assert f() == 'z' + res = interpret(f, []) + assert res == 'z' + def test_funcptr1(self): def dummy(n): return n+1 @@ -789,3 +817,13 @@ c1 = lltype2ctypes(a1) c2 = lltype2ctypes(a2) assert type(c1) is type(c2) + + def test_varsized_struct(self): + STR = lltype.Struct('rpy_string', ('hash', lltype.Signed), + ('chars', lltype.Array(lltype.Char, hints={'immutable': True}))) + s = lltype.malloc(STR, 3, flavor='raw') + one = force_cast(rffi.VOIDP, s) + # sanity check + #assert lltype2ctypes(one).contents.items._length_ > 0 + two = force_cast(lltype.Ptr(STR), one) + assert s == two Modified: pypy/branch/hybrid-io/pypy/rpython/lltypesystem/test/test_llmemory.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/lltypesystem/test/test_llmemory.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/lltypesystem/test/test_llmemory.py Sun May 11 12:45:47 2008 @@ -602,3 +602,13 @@ py.test.raises(TypeError, "sizeof(S1) <= 0") py.test.raises(TypeError, "sizeof(S1) <= 4") py.test.raises(TypeError, "(-sizeof(S1)) >= 0") + +def test_addr_keeps_object_alive(): + A = lltype.Array(Address) + ptr = lltype.malloc(A, 10, immortal=True) + adr = cast_ptr_to_adr(ptr) + ArrayItemsOffset(A) + del ptr + import gc; gc.collect(); gc.collect() + # the following line crashes if the array is dead + ptr1 = cast_adr_to_ptr(adr, lltype.Ptr(lltype.FixedSizeArray(Address, 1))) + ptr1[0] = NULL Modified: pypy/branch/hybrid-io/pypy/rpython/lltypesystem/test/test_lltype.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/lltypesystem/test/test_lltype.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/lltypesystem/test/test_lltype.py Sun May 11 12:45:47 2008 @@ -727,3 +727,11 @@ setattr(s, word, i) for i, word in enumerate(words): assert getattr(s, word) == i + +def test_subarray_keeps_array_alive(): + A = Array(Signed) + ptr = malloc(A, 10, immortal=True) + ptr2 = direct_arrayitems(ptr) + del ptr + import gc; gc.collect(); gc.collect() + ptr2[0] = 5 # crashes if the array was deallocated Modified: pypy/branch/hybrid-io/pypy/rpython/lltypesystem/test/test_rffi.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/lltypesystem/test/test_rffi.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/lltypesystem/test/test_rffi.py Sun May 11 12:45:47 2008 @@ -6,9 +6,11 @@ from pypy.translator.c.test.test_genc import compile as compile_c from pypy.translator.llvm.test.runtest import compile_function as compile_llvm from pypy.rpython.lltypesystem.lltype import Signed, Ptr, Char, malloc +from pypy.rpython.lltypesystem.rstr import STR from pypy.rpython.lltypesystem import lltype from pypy.tool.udir import udir from pypy.rpython.test.test_llinterp import interpret, MallocMismatch +from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin from pypy.annotation.annrpython import RPythonAnnotator from pypy.rpython.rtyper import RPythonTyper from pypy.translator.backendopt.all import backend_optimizations @@ -429,6 +431,50 @@ unregister_keepalive(pos, TP) assert res == 8 + def test_nonmoving(self): + d = 'non-moving data stuff' + def f(): + raw_buf, gc_buf = alloc_buffer(len(d)) + try: + for i in range(len(d)): + raw_buf[i] = d[i] + return str_from_buffer(raw_buf, gc_buf, len(d), len(d)-1) + finally: + keep_buffer_alive_until_here(raw_buf, gc_buf) + fn = self.compile(f, [], gcpolicy='ref') + assert fn() == d[:-1] + + + def test_nonmovingbuffer(self): + d = 'some cool data that should not move' + def f(): + buf = get_nonmovingbuffer(d) + try: + counter = 0 + for i in range(len(d)): + if buf[i] == d[i]: + counter += 1 + return counter + finally: + free_nonmovingbuffer(d, buf) + fn = self.compile(f, [], gcpolicy='ref') + assert fn() == len(d) + + def test_nonmovingbuffer_semispace(self): + d = 'some cool data that should not move' + def f(): + buf = get_nonmovingbuffer(d) + try: + counter = 0 + for i in range(len(d)): + if buf[i] == d[i]: + counter += 1 + return counter + finally: + free_nonmovingbuffer(d, buf) + fn = self.compile(f, [], gcpolicy='semispace') + assert fn(expected_extra_mallocs=9) == len(d) + class TestRffiInternals: def test_struct_create(self): X = CStruct('xx', ('one', INT)) @@ -481,8 +527,7 @@ graph = graphof(a.translator, f) s = summary(graph) # there should be not too many operations here by now - expected = {'cast_int_to_uint': 1, 'direct_call': 1, - 'cast_primitive': 2, 'cast_int_to_float': 1} + expected = {'force_cast': 3, 'cast_int_to_float': 1, 'direct_call': 1} for k, v in expected.items(): assert s[k] == v @@ -634,7 +679,6 @@ def test_ptradd_interpret(): interpret(test_ptradd, []) - class TestCRffi(BaseTestRffi): def compile(self, func, args, **kwds): return compile_c(func, args, **kwds) @@ -650,5 +694,13 @@ del kwds['backendopt'] return compile_llvm(func, args, **kwds) + def test_nonmovingbuffer(self): + py.test.skip("Somewhat buggy...") + + test_nonmoving = test_nonmovingbuffer + + def test_nonmovingbuffer_semispace(self): + py.test.skip("LLVM backend error - unsupported operator") + def test_hashdefine(self): py.test.skip("Macros cannot be called as llexternals by design, rffi does not have any special support for them") Modified: pypy/branch/hybrid-io/pypy/rpython/memory/gc/base.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/memory/gc/base.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/memory/gc/base.py Sun May 11 12:45:47 2008 @@ -7,6 +7,7 @@ needs_write_barrier = False malloc_zero_filled = False prebuilt_gc_objects_are_static_roots = True + can_realloc = False # The following flag enables costly consistency checks after each # collection. It is automatically set to True by test_gc.py. The @@ -50,16 +51,13 @@ def size_gc_header(self, typeid=0): return self.gcheaderbuilder.size_gc_header - def malloc(self, typeid, length=0, zero=False, coallocator=None): + def malloc(self, typeid, length=0, zero=False): """For testing. The interface used by the gctransformer is the four malloc_[fixed,var]size[_clear]() functions. - And (if they exist) to the coalloc_[fixed,var]size_clear functions """ # Rules about fallbacks in case of missing malloc methods: # * malloc_fixedsize_clear() and malloc_varsize_clear() are mandatory # * malloc_fixedsize() and malloc_varsize() fallback to the above - # * coalloc_fixedsize_clear() and coalloc_varsize_clear() are optional - # There is no non-clear version of coalloc for now. # XXX: as of r49360, gctransformer.framework never inserts calls # to malloc_varsize(), but always uses malloc_varsize_clear() @@ -71,39 +69,28 @@ assert not contains_weakptr itemsize = self.varsize_item_sizes(typeid) offset_to_length = self.varsize_offset_to_length(typeid) - if (coallocator is not None and - hasattr(self, "coalloc_varsize_clear")): - assert not needs_finalizer - coallocator = llmemory.cast_ptr_to_adr(coallocator) - ref = self.coalloc_varsize_clear(coallocator, typeid, - length, size, - itemsize, offset_to_length) + if zero or not hasattr(self, 'malloc_varsize'): + malloc_varsize = self.malloc_varsize_clear else: - if zero or not hasattr(self, 'malloc_varsize'): - malloc_varsize = self.malloc_varsize_clear - else: - malloc_varsize = self.malloc_varsize - ref = malloc_varsize(typeid, length, size, itemsize, - offset_to_length, True, needs_finalizer) + malloc_varsize = self.malloc_varsize + ref = malloc_varsize(typeid, length, size, itemsize, + offset_to_length, True, needs_finalizer) else: - if (coallocator is not None and - hasattr(self, "coalloc_fixedsize_clear")): - assert not needs_finalizer - coallocator = llmemory.cast_ptr_to_adr(coallocator) - ref = self.coalloc_fixedsize_clear(coallocator, typeid, size) + if zero or not hasattr(self, 'malloc_fixedsize'): + malloc_fixedsize = self.malloc_fixedsize_clear else: - if zero or not hasattr(self, 'malloc_fixedsize'): - malloc_fixedsize = self.malloc_fixedsize_clear - else: - malloc_fixedsize = self.malloc_fixedsize - ref = malloc_fixedsize(typeid, size, True, needs_finalizer, - contains_weakptr) + malloc_fixedsize = self.malloc_fixedsize + ref = malloc_fixedsize(typeid, size, True, needs_finalizer, + contains_weakptr) # lots of cast and reverse-cast around... return llmemory.cast_ptr_to_adr(ref) def id(self, ptr): return lltype.cast_ptr_to_int(ptr) + def can_move(self, addr): + return False + def set_max_heap_size(self, size): pass @@ -198,6 +185,8 @@ class MovingGCBase(GCBase): moving_gc = True + def can_move(self, addr): + return True def choose_gc_from_config(config): """Return a (GCClass, GC_PARAMS) from the given config object. Modified: pypy/branch/hybrid-io/pypy/rpython/memory/gc/generation.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/memory/gc/generation.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/memory/gc/generation.py Sun May 11 12:45:47 2008 @@ -159,18 +159,6 @@ self.young_objects_with_weakrefs.append(result + size_gc_header) return llmemory.cast_adr_to_ptr(result+size_gc_header, llmemory.GCREF) - def coalloc_fixedsize_clear(self, coallocator, typeid, size): - # note: a coallocated object can never return a weakref, since the - # coallocation analysis is done at a time where weakrefs are - # represented as opaque objects which aren't allocated using malloc but - # with weakref_create - if self.is_in_nursery(coallocator): - return self.malloc_fixedsize_clear(typeid, size, - True, False, False) - else: - return SemiSpaceGC.malloc_fixedsize_clear(self, typeid, size, - True, False, False) - def malloc_varsize_clear(self, typeid, length, size, itemsize, offset_to_length, can_collect, has_finalizer=False): @@ -218,17 +206,6 @@ self.nursery_free = result + llarena.round_up_for_allocation(totalsize) return llmemory.cast_adr_to_ptr(result+size_gc_header, llmemory.GCREF) - def coalloc_varsize_clear(self, coallocator, typeid, - length, size, itemsize, - offset_to_length): - if self.is_in_nursery(coallocator): - return self.malloc_varsize_clear(typeid, length, size, itemsize, - offset_to_length, True, False) - else: - return SemiSpaceGC.malloc_varsize_clear(self, typeid, length, size, - itemsize, offset_to_length, - True, False) - # override the init_gc_object methods to change the default value of 'flags', # used by objects that are directly created outside the nursery by the SemiSpaceGC. # These objects must have the GCFLAG_NO_YOUNG_PTRS flag set immediately. Modified: pypy/branch/hybrid-io/pypy/rpython/memory/gctransform/boehm.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/memory/gctransform/boehm.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/memory/gctransform/boehm.py Sun May 11 12:45:47 2008 @@ -4,6 +4,8 @@ from pypy.rpython.lltypesystem import lltype, llmemory from pypy.objspace.flow.model import Constant from pypy.rpython.lltypesystem.lloperation import llop +from pypy.rpython.lltypesystem import rffi +from pypy.rpython import rmodel class BoehmGCTransformer(GCTransformer): malloc_zero_filled = True @@ -19,12 +21,19 @@ mh = mallocHelpers() mh.allocate = lambda size: llop.boehm_malloc(llmemory.Address, size) + c_realloc = rffi.llexternal('GC_REALLOC', [rffi.VOIDP, rffi.INT], + rffi.VOIDP) + def _realloc(ptr, size): + return llmemory.cast_ptr_to_adr(c_realloc(rffi.cast(rffi.VOIDP, ptr), size)) + mh.realloc = _realloc ll_malloc_fixedsize = mh._ll_malloc_fixedsize # XXX, do we need/want an atomic version of this function? ll_malloc_varsize_no_length = mh.ll_malloc_varsize_no_length ll_malloc_varsize = mh.ll_malloc_varsize + ll_realloc = mh.ll_realloc + if self.translator: self.malloc_fixedsize_ptr = self.inittime_helper( ll_malloc_fixedsize, [lltype.Signed], llmemory.Address) @@ -39,6 +48,9 @@ inline=False) self.weakref_deref_ptr = self.inittime_helper( ll_weakref_deref, [llmemory.WeakRefPtr], llmemory.Address) + self.realloc_ptr = self.inittime_helper( + ll_realloc, [llmemory.Address] + [lltype.Signed] * 4, + llmemory.Address) self.mixlevelannotator.finish() # for now self.mixlevelannotator.backend_optimize() @@ -48,6 +60,15 @@ def pop_alive_nopyobj(self, var, llops): pass + def _can_realloc(self): + return True + + def perform_realloc(self, hop, v_ptr, v_newlgt, c_const_size, c_item_size, + c_lengthofs): + args = [self.realloc_ptr, v_ptr, v_newlgt, c_const_size, + c_item_size, c_lengthofs] + return hop.genop('direct_call', args, resulttype=llmemory.Address) + def gct_fv_gc_malloc(self, hop, flags, TYPE, c_size): # XXX same behavior for zero=True: in theory that's wrong if TYPE._is_atomic(): @@ -63,7 +84,6 @@ hop.genop("boehm_register_finalizer", [v_raw, c_finalizer_ptr]) return v_raw - def gct_fv_gc_malloc_varsize(self, hop, flags, TYPE, v_length, c_const_size, c_item_size, c_offset_to_length): # XXX same behavior for zero=True: in theory that's wrong Modified: pypy/branch/hybrid-io/pypy/rpython/memory/gctransform/framework.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/memory/gctransform/framework.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/memory/gctransform/framework.py Sun May 11 12:45:47 2008 @@ -221,6 +221,9 @@ [s_gc], annmodel.s_None) self.enable_finalizers_ptr = getfn(GCClass.enable_finalizers.im_func, [s_gc], annmodel.s_None) + self.can_move_ptr = getfn(GCClass.can_move.im_func, + [s_gc, annmodel.SomeAddress()], + annmodel.SomeBool()) # in some GCs we can inline the common case of # malloc_fixedsize(typeid, size, True, False, False) @@ -292,20 +295,6 @@ inline=True) else: self.write_barrier_ptr = None - if hasattr(GCClass, "coalloc_fixedsize_clear"): - self.coalloc_clear_ptr = getfn( - GCClass.coalloc_fixedsize_clear.im_func, - [s_gc, annmodel.SomeAddress(), - annmodel.SomeInteger(nonneg=True), - annmodel.SomeInteger(nonneg=True)], - s_gcref, inline=True) - self.coalloc_varsize_clear_ptr = getfn( - GCClass.coalloc_varsize_clear.im_func, - [s_gc, annmodel.SomeAddress()] + - [annmodel.SomeInteger(nonneg=True) for i in range(5)], - s_gcref, inline=True) - else: - self.coalloc_clear_ptr = self.coalloc_varsize_clear_ptr = None self.statistics_ptr = getfn(GCClass.statistics.im_func, [s_gc, annmodel.SomeInteger()], annmodel.SomeInteger()) @@ -450,7 +439,7 @@ has_finalizer = bool(self.finalizer_funcptr_for_type(TYPE)) c_has_finalizer = rmodel.inputconst(lltype.Bool, has_finalizer) - if not op.opname.endswith('_varsize'): + if not op.opname.endswith('_varsize') and not flags.get('varsize'): #malloc_ptr = self.malloc_fixedsize_ptr zero = flags.get('zero', False) if (self.malloc_fast_ptr is not None and @@ -483,43 +472,6 @@ gct_fv_gc_malloc_varsize = gct_fv_gc_malloc - def gct_fv_gc_coalloc(self, hop, coallocator, flags, TYPE, *args): - if self.coalloc_clear_ptr is None: - return self.gct_fv_gc_malloc( - hop, flags, TYPE, *args) - op = hop.spaceop - flavor = flags['flavor'] - assert not flags.get("nocollect", False) - - PTRTYPE = op.result.concretetype - assert PTRTYPE.TO == TYPE - type_id = self.get_type_id(TYPE) - - c_type_id = rmodel.inputconst(lltype.Signed, type_id) - info = self.layoutbuilder.type_info_list[type_id] - c_size = rmodel.inputconst(lltype.Signed, info.fixedsize) - has_finalizer = bool(self.finalizer_funcptr_for_type(TYPE)) - assert not has_finalizer - - v_coallocator = gen_cast(hop.llops, llmemory.Address, coallocator) - - if not op.opname.endswith('_varsize'): - malloc_ptr = self.coalloc_clear_ptr - args = [self.c_const_gc, v_coallocator, c_type_id, c_size] - else: - v_length = op.args[-1] - c_ofstolength = rmodel.inputconst(lltype.Signed, info.ofstolength) - c_varitemsize = rmodel.inputconst(lltype.Signed, info.varitemsize) - malloc_ptr = self.coalloc_varsize_clear_ptr - args = [self.c_const_gc, v_coallocator, c_type_id, v_length, c_size, - c_varitemsize, c_ofstolength] - livevars = self.push_roots(hop) - v_result = hop.genop("direct_call", [malloc_ptr] + args, - resulttype=llmemory.GCREF) - self.pop_roots(hop, livevars) - return v_result - gct_fv_gc_coalloc_varsize = gct_fv_gc_coalloc - def gct_gc__collect(self, hop): op = hop.spaceop livevars = self.push_roots(hop) @@ -527,6 +479,16 @@ resultvar=op.result) self.pop_roots(hop, livevars) + def gct_gc_can_move(self, hop): + op = hop.spaceop + v_addr = hop.genop('cast_ptr_to_adr', + [op.args[0]], resulttype=llmemory.Address) + hop.genop("direct_call", [self.can_move_ptr, self.c_const_gc, v_addr], + resultvar=op.result) + + def _can_realloc(self): + return self.gcdata.gc.can_realloc + def gct_gc__disable_finalizers(self, hop): # cannot collect() op = hop.spaceop @@ -629,6 +591,22 @@ self.c_const_gc, v_size]) + def gct_malloc_nonmovable_varsize(self, hop): + TYPE = hop.spaceop.result.concretetype + if self.gcdata.gc.moving_gc: + # first approximation + c = rmodel.inputconst(TYPE, lltype.nullptr(TYPE.TO)) + return hop.cast_result(c) + return self.gct_malloc_varsize(hop) + + def gct_malloc_nonmovable(self, hop): + TYPE = hop.spaceop.result.concretetype + if self.gcdata.gc.moving_gc: + # first approximation + c = rmodel.inputconst(TYPE, lltype.nullptr(TYPE.TO)) + return hop.cast_result(c) + return self.gct_malloc(hop) + def transform_generic_set(self, hop): from pypy.objspace.flow.model import Constant opname = hop.spaceop.opname Modified: pypy/branch/hybrid-io/pypy/rpython/memory/gctransform/transform.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/memory/gctransform/transform.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/memory/gctransform/transform.py Sun May 11 12:45:47 2008 @@ -455,6 +455,15 @@ return result mh.ll_malloc_varsize_no_length_zero = _ll_malloc_varsize_no_length_zero + def ll_realloc(ptr, length, constsize, itemsize, lengthoffset): + size = constsize + length * itemsize + result = mh.realloc(ptr, size) + if not result: + raise MemoryError() + (result + lengthoffset).signed[0] = length + return result + mh.ll_realloc = ll_realloc + return mh class GCTransformer(BaseGCTransformer): @@ -496,22 +505,7 @@ c_size = rmodel.inputconst(lltype.Signed, llmemory.sizeof(TYPE)) v_raw = meth(hop, flags, TYPE, c_size) hop.cast_result(v_raw) - - def gct_coalloc(self, hop): - TYPE = hop.spaceop.result.concretetype.TO - assert not TYPE._is_varsize() - flags = hop.spaceop.args[2].value - flavor = flags['flavor'] - c_size = rmodel.inputconst(lltype.Signed, llmemory.sizeof(TYPE)) - meth = getattr(self, 'gct_fv_%s_comalloc' % flavor, None) - if meth is None: - meth = getattr(self, 'gct_fv_%s_malloc' % flavor, None) - assert meth, "%s has no support for comalloc with flavor %r" % (self, flavor) - v_raw = meth(hop, flags, TYPE, c_size) - else: - v_raw = meth(hop, hop.spaceop.args[1], flags, TYPE, c_size) - hop.cast_result(v_raw) - + def gct_fv_raw_malloc(self, hop, flags, TYPE, c_size): v_raw = hop.genop("direct_call", [self.raw_malloc_fixedsize_ptr, c_size], resulttype=llmemory.Address) @@ -535,19 +529,79 @@ assert meth, "%s has no support for malloc_varsize with flavor %r" % (self, flavor) return self.varsize_malloc_helper(hop, flags, meth, []) - def gct_coalloc_varsize(self, hop): + gct_malloc_nonmovable = gct_malloc + gct_malloc_nonmovable_varsize = gct_malloc_varsize - flags = hop.spaceop.args[2].value + def gct_malloc_resizable_buffer(self, hop): + flags = hop.spaceop.args[1].value + flags['varsize'] = True flavor = flags['flavor'] - meth = getattr(self, 'gct_fv_%s_coalloc_varsize' % flavor, None) - if meth is None: - meth = getattr(self, 'gct_fv_%s_malloc_varsize' % flavor, None) - assert meth, "%s has no support for malloc_varsize with flavor %r" % (self, flavor) - return self.varsize_malloc_helper(hop, flags, meth, []) + assert flavor != 'cpy', "cannot malloc CPython objects directly" + meth = getattr(self, 'gct_fv_%s_malloc_varsize' % flavor, None) + assert meth, "%s has no support for malloc_varsize with flavor %r" % (self, flavor) + return self.varsize_malloc_helper(hop, flags, meth, []) + + def gct_resize_buffer(self, hop): + op = hop.spaceop + if self._can_realloc(): + self._gct_resize_buffer_realloc(hop, op.args[2]) else: - return self.varsize_malloc_helper(hop, flags, meth, - [hop.spaceop.args[1]]) + self._gct_resize_buffer_no_realloc(hop, op.args[1]) + def _can_realloc(self): + return False + + def _gct_resize_buffer_realloc(self, hop, v_newsize): + def intconst(c): return rmodel.inputconst(lltype.Signed, c) + op = hop.spaceop + flags = {'flavor':'gc', 'varsize': True} + TYPE = op.args[0].concretetype.TO + ARRAY = TYPE._flds[TYPE._arrayfld] + offset_to_length = llmemory.FieldOffset(TYPE, TYPE._arrayfld) + \ + llmemory.ArrayLengthOffset(ARRAY) + c_const_size = intconst(llmemory.sizeof(TYPE, 0)) + c_item_size = intconst(llmemory.sizeof(ARRAY.OF)) + + c_lengthofs = intconst(offset_to_length) + v_ptr = op.args[0] + v_raw = self.perform_realloc(hop, v_ptr, v_newsize, c_const_size, + c_item_size, c_lengthofs) + hop.cast_result(v_raw) + + def _gct_resize_buffer_no_realloc(self, hop, v_lgt): + op = hop.spaceop + meth = self.gct_fv_gc_malloc_varsize + flags = {'flavor':'gc', 'varsize': True} + self.varsize_malloc_helper(hop, flags, meth, []) + # fish resvar + v_newbuf = hop.llops[-1].result + v_src = op.args[0] + TYPE = v_src.concretetype.TO + c_fldname = rmodel.inputconst(lltype.Void, TYPE._arrayfld) + v_adrsrc = hop.genop('cast_ptr_to_adr', [v_src], + resulttype=llmemory.Address) + v_adrnewbuf = hop.genop('cast_ptr_to_adr', [v_newbuf], + resulttype=llmemory.Address) + ofs = (llmemory.offsetof(TYPE, TYPE._arrayfld) + + llmemory.itemoffsetof(getattr(TYPE, TYPE._arrayfld), 0)) + v_ofs = rmodel.inputconst(lltype.Signed, ofs) + v_adrsrc = hop.genop('adr_add', [v_adrsrc, v_ofs], + resulttype=llmemory.Address) + v_adrnewbuf = hop.genop('adr_add', [v_adrnewbuf, v_ofs], + resulttype=llmemory.Address) + size = llmemory.sizeof(getattr(TYPE, TYPE._arrayfld).OF) + c_size = rmodel.inputconst(lltype.Signed, size) + v_lgtsym = hop.genop('int_mul', [c_size, v_lgt], + resulttype=lltype.Signed) + vlist = [v_adrsrc, v_adrnewbuf, v_lgtsym] + hop.genop('raw_memcopy', vlist) + + def gct_finish_building_buffer(self, hop): + op = hop.spaceop + if self._can_realloc(): + return self._gct_resize_buffer_realloc(hop, op.args[1]) + else: + return self._gct_resize_buffer_no_realloc(hop, op.args[1]) def varsize_malloc_helper(self, hop, flags, meth, extraargs): def intconst(c): return rmodel.inputconst(lltype.Signed, c) @@ -575,10 +629,8 @@ args = [hop] + extraargs + [flags, TYPE, op.args[-1], c_const_size, c_item_size, c_offset_to_length] v_raw = meth(*args) - hop.cast_result(v_raw) - def gct_fv_raw_malloc_varsize(self, hop, flags, TYPE, v_length, c_const_size, c_item_size, c_offset_to_length): if c_offset_to_length is None: @@ -608,3 +660,6 @@ hop.genop('raw_free', [v]) else: assert False, "%s has no support for free with flavor %r" % (self, flavor) + + def gct_gc_can_move(self, hop): + return hop.cast_result(rmodel.inputconst(lltype.Bool, False)) Modified: pypy/branch/hybrid-io/pypy/rpython/memory/gcwrapper.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/memory/gcwrapper.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/memory/gcwrapper.py Sun May 11 12:45:47 2008 @@ -44,21 +44,42 @@ else: return lltype.malloc(TYPE, n, flavor=flavor, zero=zero) + def malloc_nonmovable(self, TYPE, n=None, zero=False): + typeid = self.get_type_id(TYPE) + if self.gc.moving_gc: + return lltype.nullptr(TYPE) + addr = self.gc.malloc(typeid, n, zero=zero) + result = llmemory.cast_adr_to_ptr(addr, lltype.Ptr(TYPE)) + if not self.gc.malloc_zero_filled: + gctypelayout.zero_gc_pointers(result) + return result + + def malloc_resizable_buffer(self, TYPE, n): + typeid = self.get_type_id(TYPE) + addr = self.gc.malloc(typeid, n) + result = llmemory.cast_adr_to_ptr(addr, lltype.Ptr(TYPE)) + if not self.gc.malloc_zero_filled: + gctypelayout.zero_gc_pointers(result) + return result + + def resize_buffer(self, obj, old_size, new_size): + T = lltype.typeOf(obj).TO + buf = self.malloc_resizable_buffer(T, new_size) + # copy contents + arrayfld = T._arrayfld + new_arr = getattr(buf, arrayfld) + old_arr = getattr(obj, arrayfld) + for i in range(old_size): + new_arr[i] = old_arr[i] + return buf + + def finish_building_buffer(self, obj, size): + return obj + def free(self, TYPE, flavor='gc'): assert flavor != 'gc' return lltype.free(TYPE, flavor=flavor) - def coalloc(self, TYPE, coallocator, size=None, zero=False): - if hasattr(self.gc, "coalloc_fixedsize_clear"): - typeid = self.get_type_id(TYPE) - addr = self.gc.malloc(typeid, size, zero=zero, - coallocator=coallocator) - result = llmemory.cast_adr_to_ptr(addr, lltype.Ptr(TYPE)) - if not self.gc.malloc_zero_filled: - gctypelayout.zero_gc_pointers(result) - return result - return self.malloc(TYPE, size, 'gc', zero) - def setfield(self, obj, fieldname, fieldvalue): STRUCT = lltype.typeOf(obj).TO addr = llmemory.cast_ptr_to_adr(obj) @@ -89,6 +110,9 @@ def enable_finalizers(self): self.gc.enable_finalizers() + def can_move(self, addr): + return self.gc.can_move(addr) + def weakref_create_getlazy(self, objgetter): # we have to be lazy in reading the llinterp variable containing # the 'obj' pointer, because the gc.malloc() call below could Modified: pypy/branch/hybrid-io/pypy/rpython/memory/test/test_gc.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/memory/test/test_gc.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/memory/test/test_gc.py Sun May 11 12:45:47 2008 @@ -21,6 +21,7 @@ class GCTest(object): GC_PARAMS = {} + GC_CAN_MOVE = False def setup_class(cls): cls._saved_logstate = py.log._getstate() @@ -388,12 +389,66 @@ res = self.interpret(f, []) assert res == 42 + def test_can_move(self): + TP = lltype.GcArray(lltype.Float) + def func(): + from pypy.rlib import rgc + return rgc.can_move(lltype.malloc(TP, 1)) + assert self.interpret(func, []) == self.GC_CAN_MOVE + + + def test_malloc_nonmovable(self): + TP = lltype.GcArray(lltype.Char) + def func(): + try: + from pypy.rlib import rgc + a = rgc.malloc_nonmovable(TP, 3) + if a: + assert not rgc.can_move(a) + return 0 + return 1 + except Exception, e: + return 2 + + assert self.interpret(func, []) == int(self.GC_CAN_MOVE) + + def test_malloc_nonmovable_fixsize(self): + S = lltype.GcStruct('S', ('x', lltype.Float)) + TP = lltype.GcStruct('T', ('s', lltype.Ptr(S))) + def func(): + try: + from pypy.rlib import rgc + a = rgc.malloc_nonmovable(TP) + rgc.collect() + if a: + assert not rgc.can_move(a) + return 0 + return 1 + except Exception, e: + return 2 + + assert self.interpret(func, []) == int(self.GC_CAN_MOVE) + + def test_resizable_buffer(self): + from pypy.rpython.lltypesystem.rstr import STR + from pypy.rpython.annlowlevel import hlstr + from pypy.rlib import rgc + + def f(): + ptr = rgc.resizable_buffer_of_shape(STR, 1) + ptr.chars[0] = 'a' + ptr = rgc.resize_buffer(ptr, 1, 2) + ptr.chars[1] = 'b' + return len(hlstr(rgc.finish_building_buffer(ptr, 2))) + + assert self.interpret(f, []) == 2 class TestMarkSweepGC(GCTest): from pypy.rpython.memory.gc.marksweep import MarkSweepGC as GCClass class TestSemiSpaceGC(GCTest, snippet.SemiSpaceGCTests): from pypy.rpython.memory.gc.semispace import SemiSpaceGC as GCClass + GC_CAN_MOVE = True class TestGrowingSemiSpaceGC(TestSemiSpaceGC): GC_PARAMS = {'space_size': 64} @@ -401,20 +456,6 @@ class TestGenerationalGC(TestSemiSpaceGC): from pypy.rpython.memory.gc.generation import GenerationGC as GCClass - def test_coalloc(self): - def malloc_a_lot(): - i = 0 - while i < 10: - i += 1 - a = [1] * 10 - j = 0 - while j < 30: - j += 1 - a.append(j) - return 0 - res = self.interpret(malloc_a_lot, [], backendopt=True, coalloc=True) - assert res == 0 - class TestHybridGC(TestGenerationalGC): from pypy.rpython.memory.gc.hybrid import HybridGC as GCClass Modified: pypy/branch/hybrid-io/pypy/rpython/memory/test/test_transformed_gc.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/memory/test/test_transformed_gc.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/memory/test/test_transformed_gc.py Sun May 11 12:45:47 2008 @@ -36,6 +36,7 @@ class GCTest(object): gcpolicy = None stacklessgc = False + GC_CAN_MOVE = False def runner(self, f, nbargs=0, statistics=False, transformer=False, **extraconfigopts): @@ -446,8 +447,68 @@ res = run([]) assert res == 0 + def test_can_move(self): + TP = lltype.GcArray(lltype.Float) + def func(): + from pypy.rlib import rgc + return rgc.can_move(lltype.malloc(TP, 1)) + run = self.runner(func) + res = run([]) + assert res == self.GC_CAN_MOVE + + def test_malloc_nonmovable(self): + TP = lltype.GcArray(lltype.Char) + def func(): + try: + from pypy.rlib import rgc + a = rgc.malloc_nonmovable(TP, 3) + rgc.collect() + if a: + assert not rgc.can_move(a) + return 0 + return 1 + except Exception, e: + return 2 + + run = self.runner(func) + assert int(self.GC_CAN_MOVE) == run([]) + + def test_malloc_nonmovable_fixsize(self): + S = lltype.GcStruct('S', ('x', lltype.Float)) + TP = lltype.GcStruct('T', ('s', lltype.Ptr(S))) + def func(): + try: + from pypy.rlib import rgc + a = rgc.malloc_nonmovable(TP) + rgc.collect() + if a: + assert not rgc.can_move(a) + return 0 + return 1 + except Exception, e: + return 2 + + run = self.runner(func) + assert run([]) == int(self.GC_CAN_MOVE) + + def test_resizable_buffer(self): + from pypy.rpython.lltypesystem.rstr import STR + from pypy.rpython.annlowlevel import hlstr + from pypy.rlib import rgc + + def f(): + ptr = rgc.resizable_buffer_of_shape(STR, 2) + ptr.chars[0] = 'a' + ptr = rgc.resize_buffer(ptr, 1, 200) + ptr.chars[1] = 'b' + return hlstr(rgc.finish_building_buffer(ptr, 2)) == "ab" + + run = self.runner(f) + assert run([]) == 1 class GenericMovingGCTests(GenericGCTests): + GC_CAN_MOVE = True + def test_many_ids(self): py.test.skip("fails for bad reasons in lltype.py :-(") class A(object): @@ -476,7 +537,6 @@ run = self.runner(f) run([]) - class TestMarkSweepGC(GenericGCTests): gcname = "marksweep" class gcpolicy(gc.FrameworkGcPolicy): @@ -699,21 +759,6 @@ res = run([3, 0]) assert res == 1 - def test_coalloc(self): - def malloc_a_lot(): - i = 0 - while i < 10: - i += 1 - a = [1] * 10 - j = 0 - while j < 30: - j += 1 - a.append(j) - return 0 - run, statistics = self.runner(malloc_a_lot, statistics=True, - backendopt=True, coalloc=True) - run([]) - class TestPrintingGC(GenericGCTests): gcname = "statistics" Modified: pypy/branch/hybrid-io/pypy/rpython/module/ll_os.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/module/ll_os.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/module/ll_os.py Sun May 11 12:45:47 2008 @@ -20,10 +20,13 @@ from pypy.tool.udir import udir from pypy.translator.tool.cbuild import ExternalCompilationInfo from pypy.rpython.lltypesystem.rstr import mallocstr -from pypy.rpython.annlowlevel import hlstr -from pypy.rpython.lltypesystem.llmemory import raw_memcopy, sizeof,\ - itemoffsetof, cast_ptr_to_adr, offsetof +from pypy.rpython.annlowlevel import llstr +from pypy.rpython.lltypesystem.llmemory import sizeof,\ + itemoffsetof, cast_ptr_to_adr, cast_adr_to_ptr, offsetof from pypy.rpython.lltypesystem.rstr import STR +from pypy.rpython.annlowlevel import llstr +from pypy.rlib import rgc +from pypy.rlib.objectmodel import keepalive_until_here posix = __import__(os.name) @@ -484,20 +487,16 @@ def os_read_llimpl(fd, count): if count < 0: raise OSError(errno.EINVAL, None) - inbuf = lltype.malloc(rffi.CCHARP.TO, count, flavor='raw') + raw_buf, gc_buf = rffi.alloc_buffer(count) try: - got = rffi.cast(lltype.Signed, os_read(fd, inbuf, count)) + void_buf = rffi.cast(rffi.VOIDP, raw_buf) + got = rffi.cast(lltype.Signed, os_read(fd, void_buf, count)) if got < 0: raise OSError(rposix.get_errno(), "os_read failed") - s = mallocstr(got) - source = cast_ptr_to_adr(inbuf) + \ - itemoffsetof(lltype.typeOf(inbuf).TO, 0) - dest = cast_ptr_to_adr(s) + offset - raw_memcopy(source, dest, sizeof(lltype.Char) * got) + return rffi.str_from_buffer(raw_buf, gc_buf, count, got) finally: - lltype.free(inbuf, flavor='raw') - return hlstr(s) - + rffi.keep_buffer_alive_until_here(raw_buf, gc_buf) + def os_read_oofakeimpl(fd, count): return OOSupport.to_rstr(os.read(fd, count)) @@ -512,17 +511,15 @@ def os_write_llimpl(fd, data): count = len(data) - outbuf = lltype.malloc(rffi.CCHARP.TO, count, flavor='raw') + buf = rffi.get_nonmovingbuffer(data) try: - for i in range(count): - outbuf[i] = data[i] written = rffi.cast(lltype.Signed, os_write( rffi.cast(rffi.INT, fd), - outbuf, rffi.cast(rffi.SIZE_T, count))) + buf, rffi.cast(rffi.SIZE_T, count))) if written < 0: raise OSError(rposix.get_errno(), "os_write failed") finally: - lltype.free(outbuf, flavor='raw') + rffi.free_nonmovingbuffer(data, buf) return written def os_write_oofakeimpl(fd, data): Modified: pypy/branch/hybrid-io/pypy/rpython/module/test/test_posix.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/module/test/test_posix.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/module/test/test_posix.py Sun May 11 12:45:47 2008 @@ -72,7 +72,10 @@ def test_write(self): def f(fi): - text = 'This is a test' + if fi > 0: + text = 'This is a test' + else: + text = '333' return posix.write(fi,text) fi = os.open(path,os.O_WRONLY,0777) text = 'This is a test' Modified: pypy/branch/hybrid-io/pypy/rpython/rpbc.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/rpbc.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/rpbc.py Sun May 11 12:45:47 2008 @@ -11,6 +11,7 @@ mangle, inputdesc, warning, impossible_repr from pypy.rpython import rclass from pypy.rpython import robject +from pypy.rpython.annlowlevel import llstr from pypy.rpython import callparse @@ -605,6 +606,9 @@ def none_call(self, hop): raise TyperError("attempt to call constant None") + def ll_str(self, none): + return llstr("None") + rtype_simple_call = none_call rtype_call_args = none_call Modified: pypy/branch/hybrid-io/pypy/rpython/test/test_annlowlevel.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/test/test_annlowlevel.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/test/test_annlowlevel.py Sun May 11 12:45:47 2008 @@ -4,7 +4,7 @@ from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin from pypy.rpython.lltypesystem.rstr import mallocstr -from pypy.rpython.annlowlevel import hlstr +from pypy.rpython.annlowlevel import hlstr, llstr class TestLLType(BaseRtypingTest, LLRtypeMixin): def test_hlstr(self): @@ -13,4 +13,19 @@ s.chars[1] = "b" s.chars[2] = "c" assert hlstr(s) == "abc" + + def test_llstr(self): + s = llstr("abc") + assert len(s.chars) == 3 + assert s.chars[0] == "a" + assert s.chars[1] == "b" + assert s.chars[2] == "c" + + def test_llstr_compile(self): + def f(arg): + s = llstr(hlstr(arg)) + return len(s.chars) + + res = self.interpret(f, [self.string_to_ll("abc")]) + assert res == 3 Modified: pypy/branch/hybrid-io/pypy/rpython/test/test_rbuiltin.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/test/test_rbuiltin.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/test/test_rbuiltin.py Sun May 11 12:45:47 2008 @@ -221,10 +221,10 @@ f = file(tmpfile, 'w') f.write('hello world') f.close() - def f(): + def fn(): fd = os.open(tmpfile, os.O_RDONLY, 0777) return os.read(fd, 4096) - res = self.interpret(f, []) + res = self.interpret(fn, []) assert self.ll_to_string(res) == 'hello world' def test_os_lseek(self): Modified: pypy/branch/hybrid-io/pypy/rpython/test/test_rlist.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/test/test_rlist.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/test/test_rlist.py Sun May 11 12:45:47 2008 @@ -730,6 +730,12 @@ res = self.interpret(fn, []) assert self.ll_to_string(res) == fn() + def fn(): + return str([1.25]) + + res = self.interpret(fn, []) + assert eval(self.ll_to_string(res)) == [1.25] + def test_list_or_None(self): empty_list = [] nonempty_list = [1, 2] Modified: pypy/branch/hybrid-io/pypy/rpython/test/test_runicode.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/test/test_runicode.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/test/test_runicode.py Sun May 11 12:45:47 2008 @@ -211,10 +211,6 @@ test_float = unsupported test_hlstr = unsupported - def test_find_empty_string(self): - py.test.skip("We should think how to solve this problem") - test_rfind_empty_string = test_find_empty_string - class TestLLtype(BaseTestRUnicode, LLRtypeMixin): EMPTY_STRING_HASH = -1 Modified: pypy/branch/hybrid-io/pypy/rpython/typesystem.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/typesystem.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/typesystem.py Sun May 11 12:45:47 2008 @@ -22,7 +22,7 @@ return None if name in ('rclass', 'rpbc', 'rbuiltin', 'rtuple', 'rlist', 'rslice', 'rdict', 'rrange', 'rstr', 'rgeneric', - 'll_str', 'exceptiondata'): + 'll_str', 'rbuilder', 'exceptiondata'): mod = load(name) if mod is not None: setattr(self, name, mod) Modified: pypy/branch/hybrid-io/pypy/translator/backendopt/all.py ============================================================================== --- pypy/branch/hybrid-io/pypy/translator/backendopt/all.py (original) +++ pypy/branch/hybrid-io/pypy/translator/backendopt/all.py Sun May 11 12:45:47 2008 @@ -130,10 +130,6 @@ print "after if-to-switch:" print_statistics(translator.graphs[0], translator) - if config.coalloc and not secondary: - from pypy.translator.backendopt import coalloc - coalloc.malloc_to_coalloc(translator) - remove_obvious_noops() for graph in graphs: Modified: pypy/branch/hybrid-io/pypy/translator/c/funcgen.py ============================================================================== --- pypy/branch/hybrid-io/pypy/translator/c/funcgen.py (original) +++ pypy/branch/hybrid-io/pypy/translator/c/funcgen.py Sun May 11 12:45:47 2008 @@ -699,6 +699,8 @@ typename = cdecl(self.db.gettype(TYPE), '') return "%(result)s = (%(typename)s)(%(val)s);" % locals() + OP_FORCE_CAST = OP_CAST_PRIMITIVE # xxx the same logic works + def OP_RESUME_POINT(self, op): return '/* resume point %s */'%(op.args[0],) Modified: pypy/branch/hybrid-io/pypy/translator/c/test/test_boehm.py ============================================================================== --- pypy/branch/hybrid-io/pypy/translator/c/test/test_boehm.py (original) +++ pypy/branch/hybrid-io/pypy/translator/c/test/test_boehm.py Sun May 11 12:45:47 2008 @@ -367,6 +367,31 @@ res = c_fn(10000) assert res == 0 + def test_can_move(self): + from pypy.rlib import rgc + class A: + pass + def fn(): + return rgc.can_move(A()) + + c_fn = self.getcompiled(fn, []) + assert c_fn() == False + + def test_resizable_buffer(self): + from pypy.rpython.lltypesystem.rstr import STR + from pypy.rpython.annlowlevel import hlstr + from pypy.rlib import rgc + + def f(): + ptr = rgc.resizable_buffer_of_shape(STR, 2) + ptr.chars[0] = 'a' + ptr = rgc.resize_buffer(ptr, 1, 200) + ptr.chars[1] = 'b' + return hlstr(rgc.finish_building_buffer(ptr, 2)) == "ab" + + run = self.getcompiled(f) + assert run() == True + # reusing some tests from pypy.rpython.memory.test.snippet large_tests_ok = True Modified: pypy/branch/hybrid-io/pypy/translator/c/test/test_lltyped.py ============================================================================== --- pypy/branch/hybrid-io/pypy/translator/c/test/test_lltyped.py (original) +++ pypy/branch/hybrid-io/pypy/translator/c/test/test_lltyped.py Sun May 11 12:45:47 2008 @@ -304,6 +304,23 @@ res = fn(100) assert res == 100 + len(list(names)) + def test_force_cast(self): + from pypy.rpython.annlowlevel import llstr + from pypy.rpython.lltypesystem.rstr import STR + from pypy.rpython.lltypesystem import rffi, llmemory, lltype + P = lltype.Ptr(lltype.FixedSizeArray(lltype.Char, 1)) + + def f(): + a = llstr("xyz") + b = (llmemory.cast_ptr_to_adr(a) + llmemory.offsetof(STR, 'chars') + + llmemory.itemoffsetof(STR.chars, 0)) + buf = rffi.cast(rffi.VOIDP, b) + return buf[2] + + fn = self.getcompiled(f, []) + res = fn() + assert res == 'z' + def test_array_nolength(self): A = Array(Signed, hints={'nolength': True}) a1 = malloc(A, 3, immortal=True) Modified: pypy/branch/hybrid-io/pypy/translator/c/test/test_newgc.py ============================================================================== --- pypy/branch/hybrid-io/pypy/translator/c/test/test_newgc.py (original) +++ pypy/branch/hybrid-io/pypy/translator/c/test/test_newgc.py Sun May 11 12:45:47 2008 @@ -2,6 +2,7 @@ import sys import py from py.test import raises +import os from pypy.objspace.flow.model import summary from pypy.translator.translator import TranslationContext @@ -12,6 +13,7 @@ from pypy.rpython.memory.test import snippet from pypy.rlib.objectmodel import keepalive_until_here from pypy import conftest +from pypy.tool.udir import udir def compile_func(fn, inputtypes, t=None, gcpolicy="ref"): from pypy.config.pypyoption import get_pypy_config @@ -814,6 +816,25 @@ c_fn = self.getcompiled(f) assert c_fn() == 0 + def test_open_read_write_seek_close(self): + filename = str(udir.join('test_open_read_write_close.txt')) + def does_stuff(): + fd = os.open(filename, os.O_WRONLY | os.O_CREAT, 0777) + count = os.write(fd, "hello world\n") + assert count == len("hello world\n") + os.close(fd) + fd = os.open(filename, os.O_RDONLY, 0777) + result = os.lseek(fd, 1, 0) + assert result == 1 + data = os.read(fd, 500) + assert data == "ello world\n" + os.close(fd) + + f1 = self.getcompiled(does_stuff) + f1() + assert open(filename, 'r').read() == "hello world\n" + os.unlink(filename) + def test_callback_with_collect(self): from pypy.rlib.libffi import ffi_type_pointer, cast_type_to_ffitype,\ CDLL, ffi_type_void, CallbackFuncPtr, ffi_type_sint @@ -918,7 +939,6 @@ res = c_fn() assert res == 2 - class TestGenerationalGC(TestSemiSpaceGC): gcpolicy = "generation" should_be_moving = True Modified: pypy/branch/hybrid-io/pypy/translator/exceptiontransform.py ============================================================================== --- pypy/branch/hybrid-io/pypy/translator/exceptiontransform.py (original) +++ pypy/branch/hybrid-io/pypy/translator/exceptiontransform.py Sun May 11 12:45:47 2008 @@ -346,7 +346,10 @@ block.recloseblock(l0, l) insert_zeroing_op = False - if spaceop.opname == 'malloc': + # XXX this is not right. it also inserts zero_gc_pointers_inside + # XXX on a path that malloc_nonmovable returns null, but does not raise + # XXX which might end up with a segfault. But we don't have such gc now + if spaceop.opname == 'malloc' or spaceop.opname == 'malloc_nonmovable': flavor = spaceop.args[1].value['flavor'] if flavor == 'gc': insert_zeroing_op = True Modified: pypy/branch/hybrid-io/pypy/translator/llvm/opwriter.py ============================================================================== --- pypy/branch/hybrid-io/pypy/translator/llvm/opwriter.py (original) +++ pypy/branch/hybrid-io/pypy/translator/llvm/opwriter.py Sun May 11 12:45:47 2008 @@ -139,6 +139,8 @@ self.cast_int_to_ptr(opr) else: self.cast_primitive(opr) + elif op.opname == 'force_cast': + self.cast_primitive(opr) else: meth = getattr(self, op.opname, None) if not meth: From fijal at codespeak.net Sun May 11 12:47:10 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 11 May 2008 12:47:10 +0200 (CEST) Subject: [pypy-svn] r54650 - pypy/branch/hybrid-io/pypy/rpython/memory/test Message-ID: <20080511104710.CAADE2A80B0@codespeak.net> Author: fijal Date: Sun May 11 12:47:10 2008 New Revision: 54650 Modified: pypy/branch/hybrid-io/pypy/rpython/memory/test/test_gc.py Log: hybrid gc can move (for now) Modified: pypy/branch/hybrid-io/pypy/rpython/memory/test/test_gc.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/memory/test/test_gc.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/memory/test/test_gc.py Sun May 11 12:47:10 2008 @@ -522,6 +522,7 @@ class TestHybridGCSmallHeap(GCTest): from pypy.rpython.memory.gc.hybrid import HybridGC as GCClass + GC_CAN_MOVE = True GC_PARAMS = {'space_size': 192, 'min_nursery_size': 48, 'nursery_size': 48, From xoraxax at codespeak.net Sun May 11 13:30:39 2008 From: xoraxax at codespeak.net (xoraxax at codespeak.net) Date: Sun, 11 May 2008 13:30:39 +0200 (CEST) Subject: [pypy-svn] r54651 - pypy/extradoc/planning/roadmap Message-ID: <20080511113039.D44D116A0CE@codespeak.net> Author: xoraxax Date: Sun May 11 13:30:39 2008 New Revision: 54651 Modified: pypy/extradoc/planning/roadmap/goal_cpython_replacement.txt pypy/extradoc/planning/roadmap/task_modules_rffi.txt Log: Move ctypes task at the front (because its finished), add _ctypes as a module that could be ported to interp-level. Modified: pypy/extradoc/planning/roadmap/goal_cpython_replacement.txt ============================================================================== --- pypy/extradoc/planning/roadmap/goal_cpython_replacement.txt (original) +++ pypy/extradoc/planning/roadmap/goal_cpython_replacement.txt Sun May 11 13:30:39 2008 @@ -11,6 +11,8 @@ These tasks are loosley ordered by categories (speed, extra features, external modules) (XXX: have a more structured outline?) +.. include:: task_ctypes.txt + .. include:: task_manual_optimizations.txt .. include:: task_multi_platform.txt @@ -23,8 +25,6 @@ .. include:: task_modules_rffi.txt -.. include:: task_ctypes.txt - .. include:: task_refactor_jit.txt .. include:: task_optimize_jit.txt Modified: pypy/extradoc/planning/roadmap/task_modules_rffi.txt ============================================================================== --- pypy/extradoc/planning/roadmap/task_modules_rffi.txt (original) +++ pypy/extradoc/planning/roadmap/task_modules_rffi.txt Sun May 11 13:30:39 2008 @@ -38,6 +38,7 @@ - functools(incomplete) - imp - itertools + - _ctypes expected outcome: From fijal at codespeak.net Sun May 11 18:26:42 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 11 May 2008 18:26:42 +0200 (CEST) Subject: [pypy-svn] r54652 - in pypy/branch/hybrid-io/pypy/rpython/memory: . gc test Message-ID: <20080511162642.E6FAC16A24C@codespeak.net> Author: fijal Date: Sun May 11 18:26:40 2008 New Revision: 54652 Modified: pypy/branch/hybrid-io/pypy/rpython/memory/gc/base.py pypy/branch/hybrid-io/pypy/rpython/memory/gc/hybrid.py pypy/branch/hybrid-io/pypy/rpython/memory/gcwrapper.py pypy/branch/hybrid-io/pypy/rpython/memory/test/test_gc.py Log: Support for malloc_nonmovable (but only varsize) for hybrid gc. Only test_gc passes by now, test_transformed_gc is a next step. Modified: pypy/branch/hybrid-io/pypy/rpython/memory/gc/base.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/memory/gc/base.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/memory/gc/base.py Sun May 11 18:26:40 2008 @@ -9,6 +9,9 @@ prebuilt_gc_objects_are_static_roots = True can_realloc = False + def can_malloc_nonmovable(self): + return not self.moving_gc + # The following flag enables costly consistency checks after each # collection. It is automatically set to True by test_gc.py. The # checking logic is translatable, so the flag can be set to True @@ -85,6 +88,9 @@ # lots of cast and reverse-cast around... return llmemory.cast_ptr_to_adr(ref) + def malloc_nonmovable(self, typeid, length=0, zero=False): + return self.malloc(typeid, length, zero) + def id(self, ptr): return lltype.cast_ptr_to_int(ptr) Modified: pypy/branch/hybrid-io/pypy/rpython/memory/gc/hybrid.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/memory/gc/hybrid.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/memory/gc/hybrid.py Sun May 11 18:26:40 2008 @@ -169,7 +169,7 @@ llmemory.GCREF) return self.malloc_varsize_slowpath(typeid, length) - def malloc_varsize_slowpath(self, typeid, length): + def malloc_varsize_slowpath(self, typeid, length, force_old=False): # For objects that are too large, or when the nursery is exhausted. # In order to keep malloc_varsize_clear() as compact as possible, # we recompute what we need in this slow path instead of passing @@ -187,7 +187,7 @@ nonlarge_max = self.nonlarge_gcptrs_max else: nonlarge_max = self.nonlarge_max - if raw_malloc_usage(totalsize) > nonlarge_max: + if force_old or raw_malloc_usage(totalsize) > nonlarge_max: result = self.malloc_varsize_marknsweep(totalsize) flags = self.GCFLAGS_FOR_NEW_EXTERNAL_OBJECTS | GCFLAG_UNVISITED else: @@ -198,6 +198,19 @@ return llmemory.cast_adr_to_ptr(result+size_gc_header, llmemory.GCREF) malloc_varsize_slowpath._dont_inline_ = True + malloc_varsize_slowpath._annspecialcase_ = 'specialize:arg(3)' + + def malloc_nonmovable(self, typeid, length, zero): + # helper for testing, same as GCBase.malloc + if self.is_varsize(typeid): + gcref = self.malloc_varsize_slowpath(typeid, length, True) + else: + raise NotImplementedError("Not supported") + return llmemory.cast_ptr_to_adr(gcref) + + def can_move(self, ptr): + tid = self.get_type_id(llmemory.cast_ptr_to_adr(ptr)) + return tid & GCFLAG_AGE_MASK == GCFLAG_AGE_MAX def malloc_varsize_collecting_nursery(self, totalsize): result = self.collect_nursery() @@ -515,3 +528,6 @@ "gen3: unexpected GCFLAG_UNVISITED") ll_assert((tid & GCFLAG_AGE_MASK) == GCFLAG_AGE_MAX, "gen3: wrong age field") + + def can_malloc_nonmovable(self): + return True Modified: pypy/branch/hybrid-io/pypy/rpython/memory/gcwrapper.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/memory/gcwrapper.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/memory/gcwrapper.py Sun May 11 18:26:40 2008 @@ -46,9 +46,9 @@ def malloc_nonmovable(self, TYPE, n=None, zero=False): typeid = self.get_type_id(TYPE) - if self.gc.moving_gc: + if not self.gc.can_malloc_nonmovable(): return lltype.nullptr(TYPE) - addr = self.gc.malloc(typeid, n, zero=zero) + addr = self.gc.malloc_nonmovable(typeid, n, zero=zero) result = llmemory.cast_adr_to_ptr(addr, lltype.Ptr(TYPE)) if not self.gc.malloc_zero_filled: gctypelayout.zero_gc_pointers(result) Modified: pypy/branch/hybrid-io/pypy/rpython/memory/test/test_gc.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/memory/test/test_gc.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/memory/test/test_gc.py Sun May 11 18:26:40 2008 @@ -22,6 +22,7 @@ class GCTest(object): GC_PARAMS = {} GC_CAN_MOVE = False + GC_CANNOT_MALLOC_NONMOVABLE = False def setup_class(cls): cls._saved_logstate = py.log._getstate() @@ -400,17 +401,14 @@ def test_malloc_nonmovable(self): TP = lltype.GcArray(lltype.Char) def func(): - try: - from pypy.rlib import rgc - a = rgc.malloc_nonmovable(TP, 3) - if a: - assert not rgc.can_move(a) - return 0 - return 1 - except Exception, e: - return 2 + from pypy.rlib import rgc + a = rgc.malloc_nonmovable(TP, 3) + if a: + assert not rgc.can_move(a) + return 0 + return 1 - assert self.interpret(func, []) == int(self.GC_CAN_MOVE) + assert self.interpret(func, []) == int(self.GC_CANNOT_MALLOC_NONMOVABLE) def test_malloc_nonmovable_fixsize(self): S = lltype.GcStruct('S', ('x', lltype.Float)) @@ -427,7 +425,7 @@ except Exception, e: return 2 - assert self.interpret(func, []) == int(self.GC_CAN_MOVE) + assert self.interpret(func, []) == int(self.GC_CANNOT_MALLOC_NONMOVABLE) def test_resizable_buffer(self): from pypy.rpython.lltypesystem.rstr import STR @@ -449,6 +447,7 @@ class TestSemiSpaceGC(GCTest, snippet.SemiSpaceGCTests): from pypy.rpython.memory.gc.semispace import SemiSpaceGC as GCClass GC_CAN_MOVE = True + GC_CANNOT_MALLOC_NONMOVABLE = True class TestGrowingSemiSpaceGC(TestSemiSpaceGC): GC_PARAMS = {'space_size': 64} @@ -458,6 +457,7 @@ class TestHybridGC(TestGenerationalGC): from pypy.rpython.memory.gc.hybrid import HybridGC as GCClass + GC_CANNOT_MALLOC_NONMOVABLE = False def test_ref_from_rawmalloced_to_regular(self): import gc @@ -520,9 +520,13 @@ res = self.interpret(f, [15]) assert res == 16 + def test_malloc_nonmovable_fixsize(self): + py.test.skip("Not supported") + class TestHybridGCSmallHeap(GCTest): from pypy.rpython.memory.gc.hybrid import HybridGC as GCClass GC_CAN_MOVE = True + GC_CANNOT_MALLOC_NONMOVABLE = False GC_PARAMS = {'space_size': 192, 'min_nursery_size': 48, 'nursery_size': 48, @@ -563,3 +567,6 @@ return i res = self.interpret(f, [200]) assert res == 401 + + def test_malloc_nonmovable_fixsize(self): + py.test.skip("Not supported") From fijal at codespeak.net Sun May 11 18:44:10 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 11 May 2008 18:44:10 +0200 (CEST) Subject: [pypy-svn] r54653 - in pypy/branch/hybrid-io/pypy/rpython/memory: gc test Message-ID: <20080511164410.D8AB42A80B7@codespeak.net> Author: fijal Date: Sun May 11 18:44:08 2008 New Revision: 54653 Modified: pypy/branch/hybrid-io/pypy/rpython/memory/gc/hybrid.py pypy/branch/hybrid-io/pypy/rpython/memory/test/test_gc.py Log: Fixes Modified: pypy/branch/hybrid-io/pypy/rpython/memory/gc/hybrid.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/memory/gc/hybrid.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/memory/gc/hybrid.py Sun May 11 18:44:08 2008 @@ -209,8 +209,8 @@ return llmemory.cast_ptr_to_adr(gcref) def can_move(self, ptr): - tid = self.get_type_id(llmemory.cast_ptr_to_adr(ptr)) - return tid & GCFLAG_AGE_MASK == GCFLAG_AGE_MAX + tid = self.header(llmemory.cast_ptr_to_adr(ptr)).tid + return not (tid & GCFLAG_EXTERNAL) def malloc_varsize_collecting_nursery(self, totalsize): result = self.collect_nursery() Modified: pypy/branch/hybrid-io/pypy/rpython/memory/test/test_gc.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/memory/test/test_gc.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/memory/test/test_gc.py Sun May 11 18:44:08 2008 @@ -525,7 +525,8 @@ class TestHybridGCSmallHeap(GCTest): from pypy.rpython.memory.gc.hybrid import HybridGC as GCClass - GC_CAN_MOVE = True + GC_CAN_MOVE = False # with this size of heap, stuff gets allocated + # in 3rd gen. GC_CANNOT_MALLOC_NONMOVABLE = False GC_PARAMS = {'space_size': 192, 'min_nursery_size': 48, From fijal at codespeak.net Sun May 11 19:06:31 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 11 May 2008 19:06:31 +0200 (CEST) Subject: [pypy-svn] r54654 - pypy/branch/hybrid-io/pypy/rpython/memory/gc Message-ID: <20080511170631.B93951683EA@codespeak.net> Author: fijal Date: Sun May 11 19:06:31 2008 New Revision: 54654 Modified: pypy/branch/hybrid-io/pypy/rpython/memory/gc/hybrid.py Log: oops Modified: pypy/branch/hybrid-io/pypy/rpython/memory/gc/hybrid.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/memory/gc/hybrid.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/memory/gc/hybrid.py Sun May 11 19:06:31 2008 @@ -208,8 +208,8 @@ raise NotImplementedError("Not supported") return llmemory.cast_ptr_to_adr(gcref) - def can_move(self, ptr): - tid = self.header(llmemory.cast_ptr_to_adr(ptr)).tid + def can_move(self, addr): + tid = self.header(addr).tid return not (tid & GCFLAG_EXTERNAL) def malloc_varsize_collecting_nursery(self, totalsize): From xoraxax at codespeak.net Sun May 11 19:49:34 2008 From: xoraxax at codespeak.net (xoraxax at codespeak.net) Date: Sun, 11 May 2008 19:49:34 +0200 (CEST) Subject: [pypy-svn] r54655 - in pypy/dist/pypy/translator/tool: . test Message-ID: <20080511174934.5DC76498001@codespeak.net> Author: xoraxax Date: Sun May 11 19:49:32 2008 New Revision: 54655 Modified: pypy/dist/pypy/translator/tool/cbuild.py pypy/dist/pypy/translator/tool/test/test_cbuild.py Log: try to avoid duplicates when calling merge with a long list of ecis. Modified: pypy/dist/pypy/translator/tool/cbuild.py ============================================================================== --- pypy/dist/pypy/translator/tool/cbuild.py (original) +++ pypy/dist/pypy/translator/tool/cbuild.py Sun May 11 19:49:32 2008 @@ -81,7 +81,16 @@ return "" % ", ".join(info) def merge(self, *others): - others = list(others) + def unique_elements(l): + seen = set() + new_objs = [] + for obj in l: + if obj not in seen: + new_objs.append(obj) + seen.add(obj) + return new_objs + others = unique_elements(list(others)) + attrs = {} for name in self._ATTRIBUTES: if name not in self._AVOID_DUPLICATES: Modified: pypy/dist/pypy/translator/tool/test/test_cbuild.py ============================================================================== --- pypy/dist/pypy/translator/tool/test/test_cbuild.py (original) +++ pypy/dist/pypy/translator/tool/test/test_cbuild.py Sun May 11 19:49:32 2008 @@ -74,6 +74,20 @@ assert e.includes == ('x.h', 'y.h', 'z.h') assert e.post_include_lines == ('p1', 'p2', 'p3') + def test_merge2(self): + e1 = ExternalCompilationInfo( + pre_include_lines = ['1'], + ) + e2 = ExternalCompilationInfo( + pre_include_lines = ['2'], + ) + e3 = ExternalCompilationInfo( + pre_include_lines = ['3'], + ) + e = e1.merge(e2) + e = e.merge(e3, e3) + assert e.pre_include_lines == ('1', '2', '3') + def test_convert_sources_to_c_files(self): eci = ExternalCompilationInfo( separate_module_sources = ['xxx'], From fijal at codespeak.net Sun May 11 20:32:01 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 11 May 2008 20:32:01 +0200 (CEST) Subject: [pypy-svn] r54656 - in pypy/branch/hybrid-io/pypy/rpython/memory: gc gctransform test Message-ID: <20080511183201.4C18F498001@codespeak.net> Author: fijal Date: Sun May 11 20:32:00 2008 New Revision: 54656 Modified: pypy/branch/hybrid-io/pypy/rpython/memory/gc/hybrid.py pypy/branch/hybrid-io/pypy/rpython/memory/gctransform/framework.py pypy/branch/hybrid-io/pypy/rpython/memory/gctransform/transform.py pypy/branch/hybrid-io/pypy/rpython/memory/test/test_transformed_gc.py Log: Implement basic version of malloc_nonmovable for hybrid gc Modified: pypy/branch/hybrid-io/pypy/rpython/memory/gc/hybrid.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/memory/gc/hybrid.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/memory/gc/hybrid.py Sun May 11 20:32:00 2008 @@ -200,6 +200,9 @@ malloc_varsize_slowpath._dont_inline_ = True malloc_varsize_slowpath._annspecialcase_ = 'specialize:arg(3)' + def malloc_varsize_nonmovable(self, typeid, length): + return self.malloc_varsize_slowpath(typeid, length, True) + def malloc_nonmovable(self, typeid, length, zero): # helper for testing, same as GCBase.malloc if self.is_varsize(typeid): Modified: pypy/branch/hybrid-io/pypy/rpython/memory/gctransform/framework.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/memory/gctransform/framework.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/memory/gctransform/framework.py Sun May 11 20:32:00 2008 @@ -273,6 +273,17 @@ else: self.malloc_varsize_clear_fast_ptr = None + if getattr(GCClass, 'malloc_varsize_nonmovable', False): + malloc_nonmovable = func_with_new_name( + GCClass.malloc_varsize_nonmovable.im_func, + "malloc_varsize_nonmovable") + self.malloc_varsize_nonmovable_ptr = getfn( + malloc_nonmovable, + [s_gc, annmodel.SomeInteger(nonneg=True), + annmodel.SomeInteger(nonneg=True)], s_gcref) + else: + self.malloc_varsize_nonmovable_ptr = None + if GCClass.moving_gc: self.id_ptr = getfn(GCClass.id.im_func, [s_gc, s_gcref], annmodel.SomeInteger(), @@ -456,14 +467,22 @@ v_length = op.args[-1] c_ofstolength = rmodel.inputconst(lltype.Signed, info.ofstolength) c_varitemsize = rmodel.inputconst(lltype.Signed, info.varitemsize) - if (self.malloc_varsize_clear_fast_ptr is not None and - c_can_collect.value and not c_has_finalizer.value): - malloc_ptr = self.malloc_varsize_clear_fast_ptr + if flags.get('nonmovable') and self.malloc_varsize_nonmovable_ptr: + # we don't have tests for such cases, let's fail + # explicitely + assert c_can_collect.value + assert not c_has_finalizer.value + malloc_ptr = self.malloc_varsize_nonmovable_ptr + args = [self.c_const_gc, c_type_id, v_length] else: - malloc_ptr = self.malloc_varsize_clear_ptr - args = [self.c_const_gc, c_type_id, v_length, c_size, - c_varitemsize, c_ofstolength, c_can_collect, - c_has_finalizer] + if (self.malloc_varsize_clear_fast_ptr is not None and + c_can_collect.value and not c_has_finalizer.value): + malloc_ptr = self.malloc_varsize_clear_fast_ptr + else: + malloc_ptr = self.malloc_varsize_clear_ptr + args = [self.c_const_gc, c_type_id, v_length, c_size, + c_varitemsize, c_ofstolength, c_can_collect, + c_has_finalizer] livevars = self.push_roots(hop) v_result = hop.genop("direct_call", [malloc_ptr] + args, resulttype=llmemory.GCREF) @@ -593,19 +612,17 @@ def gct_malloc_nonmovable_varsize(self, hop): TYPE = hop.spaceop.result.concretetype - if self.gcdata.gc.moving_gc: - # first approximation - c = rmodel.inputconst(TYPE, lltype.nullptr(TYPE.TO)) - return hop.cast_result(c) - return self.gct_malloc_varsize(hop) + if self.gcdata.gc.can_malloc_nonmovable(): + return self.gct_malloc_varsize(hop, {'nonmovable':True}) + c = rmodel.inputconst(TYPE, lltype.nullptr(TYPE.TO)) + return hop.cast_result(c) def gct_malloc_nonmovable(self, hop): TYPE = hop.spaceop.result.concretetype - if self.gcdata.gc.moving_gc: - # first approximation - c = rmodel.inputconst(TYPE, lltype.nullptr(TYPE.TO)) - return hop.cast_result(c) - return self.gct_malloc(hop) + if self.gcdata.gc.can_malloc_nonmovable(): + return self.gct_malloc(hop, {'nonmovable':True}) + c = rmodel.inputconst(TYPE, lltype.nullptr(TYPE.TO)) + return hop.cast_result(c) def transform_generic_set(self, hop): from pypy.objspace.flow.model import Constant Modified: pypy/branch/hybrid-io/pypy/rpython/memory/gctransform/transform.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/memory/gctransform/transform.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/memory/gctransform/transform.py Sun May 11 20:32:00 2008 @@ -495,7 +495,7 @@ self.stack_malloc_fixedsize_ptr = self.inittime_helper( ll_stack_malloc_fixedsize, [lltype.Signed], llmemory.Address) - def gct_malloc(self, hop): + def gct_malloc(self, hop, add_flags=None): TYPE = hop.spaceop.result.concretetype.TO assert not TYPE._is_varsize() flags = hop.spaceop.args[1].value @@ -520,17 +520,21 @@ hop.genop("raw_memclear", [v_raw, c_size]) return v_raw - def gct_malloc_varsize(self, hop): - + def gct_malloc_varsize(self, hop, add_flags=None): flags = hop.spaceop.args[1].value + if add_flags: + flags.update(add_flags) flavor = flags['flavor'] assert flavor != 'cpy', "cannot malloc CPython objects directly" meth = getattr(self, 'gct_fv_%s_malloc_varsize' % flavor, None) assert meth, "%s has no support for malloc_varsize with flavor %r" % (self, flavor) return self.varsize_malloc_helper(hop, flags, meth, []) - gct_malloc_nonmovable = gct_malloc - gct_malloc_nonmovable_varsize = gct_malloc_varsize + def gct_malloc_nonmovable(self, *args, **kwds): + return self.gct_malloc(*args, **kwds) + + def gct_malloc_nonmovable_varsize(self, *args, **kwds): + return self.gct_malloc_varsize(*args, **kwds) def gct_malloc_resizable_buffer(self, hop): flags = hop.spaceop.args[1].value Modified: pypy/branch/hybrid-io/pypy/rpython/memory/test/test_transformed_gc.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/memory/test/test_transformed_gc.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/memory/test/test_transformed_gc.py Sun May 11 20:32:00 2008 @@ -37,6 +37,7 @@ gcpolicy = None stacklessgc = False GC_CAN_MOVE = False + GC_CANNOT_MALLOC_NONMOVABLE = False def runner(self, f, nbargs=0, statistics=False, transformer=False, **extraconfigopts): @@ -459,19 +460,19 @@ def test_malloc_nonmovable(self): TP = lltype.GcArray(lltype.Char) def func(): - try: - from pypy.rlib import rgc - a = rgc.malloc_nonmovable(TP, 3) - rgc.collect() - if a: - assert not rgc.can_move(a) - return 0 - return 1 - except Exception, e: - return 2 + #try: + from pypy.rlib import rgc + a = rgc.malloc_nonmovable(TP, 3) + rgc.collect() + if a: + assert not rgc.can_move(a) + return 0 + return 1 + #except Exception, e: + # return 2 run = self.runner(func) - assert int(self.GC_CAN_MOVE) == run([]) + assert int(self.GC_CANNOT_MALLOC_NONMOVABLE) == run([]) def test_malloc_nonmovable_fixsize(self): S = lltype.GcStruct('S', ('x', lltype.Float)) @@ -489,7 +490,7 @@ return 2 run = self.runner(func) - assert run([]) == int(self.GC_CAN_MOVE) + assert run([]) == int(self.GC_CANNOT_MALLOC_NONMOVABLE) def test_resizable_buffer(self): from pypy.rpython.lltypesystem.rstr import STR @@ -508,6 +509,7 @@ class GenericMovingGCTests(GenericGCTests): GC_CAN_MOVE = True + GC_CANNOT_MALLOC_NONMOVABLE = True def test_many_ids(self): py.test.skip("fails for bad reasons in lltype.py :-(") @@ -956,6 +958,7 @@ class TestHybridGC(TestGenerationGC): gcname = "hybrid" + GC_CANNOT_MALLOC_NONMOVABLE = False class gcpolicy(gc.FrameworkGcPolicy): class transformerclass(framework.FrameworkGCTransformer): @@ -986,3 +989,6 @@ run = self.runner(f, nbargs=2) res = run([100, 100]) assert res == 200 + + def test_malloc_nonmovable_fixsize(self): + py.test.skip("not supported") From arigo at codespeak.net Sun May 11 20:37:57 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 11 May 2008 20:37:57 +0200 (CEST) Subject: [pypy-svn] r54657 - pypy/dist/pypy/rpython/memory/gc Message-ID: <20080511183757.1958A498001@codespeak.net> Author: arigo Date: Sun May 11 20:37:55 2008 New Revision: 54657 Modified: pypy/dist/pypy/rpython/memory/gc/hybrid.py Log: Add a comment about a bug that may be an optimization. Modified: pypy/dist/pypy/rpython/memory/gc/hybrid.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gc/hybrid.py (original) +++ pypy/dist/pypy/rpython/memory/gc/hybrid.py Sun May 11 20:37:55 2008 @@ -321,6 +321,12 @@ # some threshold is reached we make the copy a non-movable "external" # object. The threshold is MAX_SEMISPACE_AGE. tid = self.header(obj).tid + # XXX the following logic is not doing exactly what is explained + # above: any object without GCFLAG_NO_YOUNG_PTRS has its age not + # incremented. This is accidental: it means that objects that + # are very often modified to point to young objects don't reach + # the 3rd generation. For now I'll leave it this way because + # I'm not sure that it's a bad thing. if not (tid & GCFLAG_NO_YOUNG_PTRS): tid |= GCFLAG_NO_YOUNG_PTRS # object comes from the nursery elif (tid & GCFLAG_AGE_MASK) < GCFLAG_AGE_MAX: From fijal at codespeak.net Sun May 11 23:10:01 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 11 May 2008 23:10:01 +0200 (CEST) Subject: [pypy-svn] r54659 - pypy/branch/hybrid-io/pypy/rpython Message-ID: <20080511211001.D4470169F7F@codespeak.net> Author: fijal Date: Sun May 11 23:10:00 2008 New Revision: 54659 Modified: pypy/branch/hybrid-io/pypy/rpython/llinterp.py Log: raw_realloc for llinterp Modified: pypy/branch/hybrid-io/pypy/rpython/llinterp.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/llinterp.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/llinterp.py Sun May 11 23:10:00 2008 @@ -858,6 +858,10 @@ assert lltype.typeOf(size) == lltype.Signed return llmemory.raw_malloc(size) + def op_raw_realloc(self, ptr, size): + assert lltype.typeOf(size) == lltype.Signed + return llmemory.raw_realloc(ptr, size) + op_boehm_malloc = op_boehm_malloc_atomic = op_raw_malloc def op_boehm_register_finalizer(self, p, finalizer): From fijal at codespeak.net Sun May 11 23:13:54 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 11 May 2008 23:13:54 +0200 (CEST) Subject: [pypy-svn] r54660 - pypy/branch/hybrid-io/pypy/rpython Message-ID: <20080511211354.7CE4B2A80AE@codespeak.net> Author: fijal Date: Sun May 11 23:13:54 2008 New Revision: 54660 Modified: pypy/branch/hybrid-io/pypy/rpython/llinterp.py Log: typo Modified: pypy/branch/hybrid-io/pypy/rpython/llinterp.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/llinterp.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/llinterp.py Sun May 11 23:13:54 2008 @@ -860,7 +860,7 @@ def op_raw_realloc(self, ptr, size): assert lltype.typeOf(size) == lltype.Signed - return llmemory.raw_realloc(ptr, size) + return llmemory.raw_realloc(llmemory.cast_ptr_to_adr(ptr), size) op_boehm_malloc = op_boehm_malloc_atomic = op_raw_malloc From fijal at codespeak.net Sun May 11 23:19:47 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 11 May 2008 23:19:47 +0200 (CEST) Subject: [pypy-svn] r54661 - in pypy/branch/hybrid-io/pypy/rpython/lltypesystem: . test Message-ID: <20080511211947.07E652A80AE@codespeak.net> Author: fijal Date: Sun May 11 23:19:47 2008 New Revision: 54661 Modified: pypy/branch/hybrid-io/pypy/rpython/lltypesystem/llmemory.py pypy/branch/hybrid-io/pypy/rpython/lltypesystem/test/test_llmemory.py Log: Implement raw_realloc for varsized struct as well Modified: pypy/branch/hybrid-io/pypy/rpython/lltypesystem/llmemory.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/lltypesystem/llmemory.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/lltypesystem/llmemory.py Sun May 11 23:19:47 2008 @@ -695,10 +695,20 @@ def raw_realloc(adr, size): new_area = size._raw_malloc([], zero=False) - old_len = len(adr.ptr) - new_len = len(new_area.ptr) + ptr = adr.ptr + if isinstance(lltype.typeOf(ptr).TO, lltype.Array): + from_arr = adr.ptr + to_arr = new_area.ptr + elif isinstance(lltype.typeOf(ptr).TO, lltype.Struct): + arrayfld = lltype.typeOf(ptr).TO._arrayfld + from_arr = getattr(ptr, arrayfld) + to_arr = getattr(new_area.ptr, arrayfld) + else: + raise TypeError("%s seems to be not var-sized" % (lltype.typeOf(ptr),)) + old_len = len(from_arr) + new_len = len(to_arr) for i in range(min(old_len, new_len)): - new_area.ptr[i] = adr.ptr[i] + to_arr[i] = from_arr[i] return new_area def raw_free(adr): Modified: pypy/branch/hybrid-io/pypy/rpython/lltypesystem/test/test_llmemory.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/lltypesystem/test/test_llmemory.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/lltypesystem/test/test_llmemory.py Sun May 11 23:19:47 2008 @@ -624,4 +624,16 @@ assert len(ptr2) == 5 assert ptr2[3] == 3.0 assert ptr2[1] == 1.0 - + +def test_realloc_struct(): + S = lltype.Struct('x', ('one', lltype.Signed), + ('a', lltype.Array(lltype.Float))) + adr = raw_malloc(sizeof(S, 5)) + ptr = cast_adr_to_ptr(adr, lltype.Ptr(S)) + for i in range(5): + ptr.a[i] = float(i) + adr2 = raw_realloc(adr, sizeof(S, 10)) + ptr2 = cast_adr_to_ptr(adr2, lltype.Ptr(S)) + assert len(ptr2.a) == 10 + assert ptr2.a[3] == 3.0 + assert ptr2.a[0] == 0.0 From bigdog at codespeak.net Sun May 11 23:45:01 2008 From: bigdog at codespeak.net (bigdog at codespeak.net) Date: Sun, 11 May 2008 23:45:01 +0200 (CEST) Subject: [pypy-svn] r54662 - pypy/dist/pypy/config Message-ID: <20080511214501.3A60D2A80AE@codespeak.net> Author: bigdog Date: Sun May 11 23:44:58 2008 New Revision: 54662 Modified: pypy/dist/pypy/config/pypyoption.py Log: add select and signal to modules skipped for win32 allworkingmodules. Modified: pypy/dist/pypy/config/pypyoption.py ============================================================================== --- pypy/dist/pypy/config/pypyoption.py (original) +++ pypy/dist/pypy/config/pypyoption.py Sun May 11 23:44:58 2008 @@ -35,6 +35,10 @@ del working_modules["termios"] del working_modules["_rawffi"] del working_modules["_minimal_curses"] + del working_modules["signal"] + del working_modules["select"] + + module_dependencies = {} module_suggests = { # the reason you want _rawffi is for ctypes, which From xoraxax at codespeak.net Mon May 12 01:01:39 2008 From: xoraxax at codespeak.net (xoraxax at codespeak.net) Date: Mon, 12 May 2008 01:01:39 +0200 (CEST) Subject: [pypy-svn] r54664 - pypy/dist/pypy/translator/tool Message-ID: <20080511230139.D78E416A206@codespeak.net> Author: xoraxax Date: Mon May 12 01:01:38 2008 New Revision: 54664 Modified: pypy/dist/pypy/translator/tool/cbuild.py Log: Make it possible to build .dll files on Windows again. Modified: pypy/dist/pypy/translator/tool/cbuild.py ============================================================================== --- pypy/dist/pypy/translator/tool/cbuild.py (original) +++ pypy/dist/pypy/translator/tool/cbuild.py Mon May 12 01:01:38 2008 @@ -251,6 +251,14 @@ from distutils.dist import Distribution from distutils.extension import Extension from distutils.ccompiler import get_default_compiler + from distutils.command.build_ext import build_ext + + class build_ext_no_additional_symbol(build_ext): + def get_export_symbols(self, ext): + """ work around a 'feature' of distutils that forces every + module to have a certain symbol on win """ + return ext.export_symbols + saved_environ = os.environ.items() try: # distutils.core.setup() is really meant for end-user @@ -285,9 +293,18 @@ libraries=list(libraries),) ], 'script_name': 'setup.py', - 'script_args': ['-q', 'build_ext', '--inplace', '--force'], + 'script_args': ['-q', 'build_ext'], # don't remove 'build_ext' here } dist = Distribution(attrs) + # patch our own command obj into distutils + # because it does not have a facility to accept + # custom objects + cmdobj = build_ext_no_additional_symbol(dist) + cmdobj.inplace = True + cmdobj.force = True + dist.command_obj["build_ext"] = cmdobj + dist.have_run["build_ext"] = 0 + if not dist.parse_command_line(): raise ValueError, "distutils cmdline parse error" dist.run_commands() From bigdog at codespeak.net Mon May 12 06:30:35 2008 From: bigdog at codespeak.net (bigdog at codespeak.net) Date: Mon, 12 May 2008 06:30:35 +0200 (CEST) Subject: [pypy-svn] r54665 - pypy/dist/pypy/config Message-ID: <20080512043035.A977416A1E4@codespeak.net> Author: bigdog Date: Mon May 12 06:30:34 2008 New Revision: 54665 Modified: pypy/dist/pypy/config/pypyoption.py Log: Goal: bring windows allworkingmodules translations to a running state. This changeset updates the modules to skip for windows. This list was built, one modules at a time. There are still 3 modules to validate, I will validate the remaining modules this week. On a windows machine, you should now be able to : 1) checkout pypy from svn 2) translate with the allworkingmodules options 2) run your new translated executable. Modified: pypy/dist/pypy/config/pypyoption.py ============================================================================== --- pypy/dist/pypy/config/pypyoption.py (original) +++ pypy/dist/pypy/config/pypyoption.py Mon May 12 06:30:34 2008 @@ -23,20 +23,26 @@ working_modules = default_modules.copy() working_modules.update(dict.fromkeys( - ["_socket", "unicodedata", "mmap", "fcntl", "rctime", "select", + ["_socket", "unicodedata", "mmap", "fcntl", + "rctime" , "select", "crypt", "signal", "dyngram", "_rawffi", "termios", "zlib", - "struct", "md5", "sha", "bz2", "_minimal_curses", "cStringIO", - ] + "struct", "md5", "sha", "bz2", "_minimal_curses", "cStringIO"] )) if sys.platform == "win32": - del working_modules["fcntl"] - del working_modules["crypt"] - del working_modules["termios"] + del working_modules["_socket"] # MLS - Added 5/11/08 - broken + del working_modules["mmap"] # MLS - Added 5/11/08 - broken + del working_modules["fcntl"] # UNIX only + del working_modules["select"] # MLS - Added 5/11/08 - broken + del working_modules["crypt"] # broken + del working_modules["signal"] # UNIX Only + del working_modules["zlib"] # MLS - Added 5/11/08 - broken del working_modules["_rawffi"] - del working_modules["_minimal_curses"] - del working_modules["signal"] - del working_modules["select"] + del working_modules["termios"]# UNIX Only + del working_modules["md5"]# UNKNOWN State - needs validating + del working_modules["sha"]# UNKNOWN State - needs validating + del working_modules["bz2"]# UNKNOWN State - needs validating + del working_modules["_minimal_curses"] #UNIX Only From bigdog at codespeak.net Mon May 12 07:08:14 2008 From: bigdog at codespeak.net (bigdog at codespeak.net) Date: Mon, 12 May 2008 07:08:14 +0200 (CEST) Subject: [pypy-svn] r54666 - pypy/dist/pypy/config Message-ID: <20080512050814.0777416A0CA@codespeak.net> Author: bigdog Date: Mon May 12 07:08:14 2008 New Revision: 54666 Modified: pypy/dist/pypy/config/pypyoption.py Log: update windows allworkingmodules list. md5 and sha translated with no errors on windows Modified: pypy/dist/pypy/config/pypyoption.py ============================================================================== --- pypy/dist/pypy/config/pypyoption.py (original) +++ pypy/dist/pypy/config/pypyoption.py Mon May 12 07:08:14 2008 @@ -39,8 +39,6 @@ del working_modules["zlib"] # MLS - Added 5/11/08 - broken del working_modules["_rawffi"] del working_modules["termios"]# UNIX Only - del working_modules["md5"]# UNKNOWN State - needs validating - del working_modules["sha"]# UNKNOWN State - needs validating del working_modules["bz2"]# UNKNOWN State - needs validating del working_modules["_minimal_curses"] #UNIX Only From xoraxax at codespeak.net Mon May 12 12:25:51 2008 From: xoraxax at codespeak.net (xoraxax at codespeak.net) Date: Mon, 12 May 2008 12:25:51 +0200 (CEST) Subject: [pypy-svn] r54667 - pypy/dist/pypy/config Message-ID: <20080512102551.00A88498001@codespeak.net> Author: xoraxax Date: Mon May 12 12:25:49 2008 New Revision: 54667 Modified: pypy/dist/pypy/config/pypyoption.py Log: Reorder the del working_modules and add a question. Modified: pypy/dist/pypy/config/pypyoption.py ============================================================================== --- pypy/dist/pypy/config/pypyoption.py (original) +++ pypy/dist/pypy/config/pypyoption.py Mon May 12 12:25:49 2008 @@ -30,17 +30,22 @@ )) if sys.platform == "win32": - del working_modules["_socket"] # MLS - Added 5/11/08 - broken + # unix only modules + del working_modules["crypt"] + del working_modules["fcntl"] + del working_modules["termios"] + del working_modules["_minimal_curses"] + # modules currently missing explicit windows support + del working_modules["signal"] + del working_modules["_rawffi"] + # modules with broken windows support del working_modules["mmap"] # MLS - Added 5/11/08 - broken - del working_modules["fcntl"] # UNIX only + del working_modules["_socket"] # MLS - Added 5/11/08 - broken del working_modules["select"] # MLS - Added 5/11/08 - broken - del working_modules["crypt"] # broken - del working_modules["signal"] # UNIX Only + # modules with unknown windows support + # XXX what exactly is broken here? are the libs installed on the buildbots? del working_modules["zlib"] # MLS - Added 5/11/08 - broken - del working_modules["_rawffi"] - del working_modules["termios"]# UNIX Only - del working_modules["bz2"]# UNKNOWN State - needs validating - del working_modules["_minimal_curses"] #UNIX Only + del working_modules["bz2"] # UNKNOWN State - needs validating From fijal at codespeak.net Mon May 12 12:42:33 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 12 May 2008 12:42:33 +0200 (CEST) Subject: [pypy-svn] r54668 - in pypy/branch/hybrid-io/pypy/rpython/lltypesystem: . test Message-ID: <20080512104233.AB0CC169F64@codespeak.net> Author: fijal Date: Mon May 12 12:42:31 2008 New Revision: 54668 Modified: pypy/branch/hybrid-io/pypy/rpython/lltypesystem/llmemory.py pypy/branch/hybrid-io/pypy/rpython/lltypesystem/test/test_llmemory.py Log: Make a bit more verbose interface. Later I'll think how to shrink it a bit. Modified: pypy/branch/hybrid-io/pypy/rpython/lltypesystem/llmemory.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/lltypesystem/llmemory.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/lltypesystem/llmemory.py Mon May 12 12:42:31 2008 @@ -693,22 +693,14 @@ raise NotImplementedError(size) return size._raw_malloc([], zero=False) -def raw_realloc(adr, size): +def raw_realloc_grow(addr, old_size, size): new_area = size._raw_malloc([], zero=False) - ptr = adr.ptr - if isinstance(lltype.typeOf(ptr).TO, lltype.Array): - from_arr = adr.ptr - to_arr = new_area.ptr - elif isinstance(lltype.typeOf(ptr).TO, lltype.Struct): - arrayfld = lltype.typeOf(ptr).TO._arrayfld - from_arr = getattr(ptr, arrayfld) - to_arr = getattr(new_area.ptr, arrayfld) - else: - raise TypeError("%s seems to be not var-sized" % (lltype.typeOf(ptr),)) - old_len = len(from_arr) - new_len = len(to_arr) - for i in range(min(old_len, new_len)): - to_arr[i] = from_arr[i] + raw_memcopy(addr, new_area, old_size) + return new_area + +def raw_realloc_shrink(addr, old_size, size): + new_area = size._raw_malloc([], zero=False) + raw_memcopy(addr, new_area, size) return new_area def raw_free(adr): @@ -765,7 +757,7 @@ T = lltype.typeOf(source).TO assert T == lltype.typeOf(dest).TO if isinstance(T, (lltype.Array, lltype.FixedSizeArray)): - assert source._obj.getlength() == dest._obj.getlength() + assert source._obj.getlength() <= dest._obj.getlength() ITEMTYPE = T.OF for i in range(source._obj.getlength()): if isinstance(ITEMTYPE, lltype.ContainerType): Modified: pypy/branch/hybrid-io/pypy/rpython/lltypesystem/test/test_llmemory.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/lltypesystem/test/test_llmemory.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/lltypesystem/test/test_llmemory.py Mon May 12 12:42:31 2008 @@ -619,7 +619,7 @@ ptr = cast_adr_to_ptr(adr, lltype.Ptr(A)) for i in range(10): ptr[i] = float(i) - adr2 = raw_realloc(adr, sizeof(A, 5)) + adr2 = raw_realloc_shrink(adr, sizeof(A, 10), sizeof(A, 5)) ptr2 = cast_adr_to_ptr(adr2, lltype.Ptr(A)) assert len(ptr2) == 5 assert ptr2[3] == 3.0 @@ -632,8 +632,11 @@ ptr = cast_adr_to_ptr(adr, lltype.Ptr(S)) for i in range(5): ptr.a[i] = float(i) - adr2 = raw_realloc(adr, sizeof(S, 10)) + ptr.one = 3 + adr2 = raw_realloc_grow(adr, sizeof(S, 5), sizeof(S, 10)) ptr2 = cast_adr_to_ptr(adr2, lltype.Ptr(S)) assert len(ptr2.a) == 10 assert ptr2.a[3] == 3.0 assert ptr2.a[0] == 0.0 + assert ptr2.one == 3 + From fijal at codespeak.net Mon May 12 13:38:24 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 12 May 2008 13:38:24 +0200 (CEST) Subject: [pypy-svn] r54669 - pypy/branch/hybrid-io/pypy/rpython/lltypesystem Message-ID: <20080512113824.1F69E169FDF@codespeak.net> Author: fijal Date: Mon May 12 13:38:23 2008 New Revision: 54669 Modified: pypy/branch/hybrid-io/pypy/rpython/lltypesystem/llmemory.py pypy/branch/hybrid-io/pypy/rpython/lltypesystem/lloperation.py Log: * widen memcopy a bit to copy between different sizes (copies min than) * realloc_grow and realloc_shrink ops Modified: pypy/branch/hybrid-io/pypy/rpython/lltypesystem/llmemory.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/lltypesystem/llmemory.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/lltypesystem/llmemory.py Mon May 12 13:38:23 2008 @@ -757,9 +757,11 @@ T = lltype.typeOf(source).TO assert T == lltype.typeOf(dest).TO if isinstance(T, (lltype.Array, lltype.FixedSizeArray)): - assert source._obj.getlength() <= dest._obj.getlength() + sourcelgt = source._obj.getlength() + destlgt = dest._obj.getlength() + lgt = min(sourcelgt, destlgt) ITEMTYPE = T.OF - for i in range(source._obj.getlength()): + for i in range(lgt): if isinstance(ITEMTYPE, lltype.ContainerType): subsrc = source._obj.getitem(i)._as_ptr() subdst = dest._obj.getitem(i)._as_ptr() Modified: pypy/branch/hybrid-io/pypy/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/lltypesystem/lloperation.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/lltypesystem/lloperation.py Mon May 12 13:38:23 2008 @@ -362,7 +362,8 @@ 'boehm_register_finalizer': LLOp(), 'boehm_disappearing_link': LLOp(), 'raw_malloc': LLOp(), - 'raw_realloc': LLOp(), + 'raw_realloc_grow': LLOp(), + 'raw_realloc_shrink': LLOp(), 'raw_malloc_usage': LLOp(sideeffects=False), 'raw_free': LLOp(), 'raw_memclear': LLOp(), From fijal at codespeak.net Mon May 12 13:38:41 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 12 May 2008 13:38:41 +0200 (CEST) Subject: [pypy-svn] r54670 - pypy/branch/hybrid-io/pypy/rpython Message-ID: <20080512113841.18725169FDB@codespeak.net> Author: fijal Date: Mon May 12 13:38:40 2008 New Revision: 54670 Modified: pypy/branch/hybrid-io/pypy/rpython/llinterp.py Log: implement realloc_grow and realloc_shrink Modified: pypy/branch/hybrid-io/pypy/rpython/llinterp.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/llinterp.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/llinterp.py Mon May 12 13:38:40 2008 @@ -858,9 +858,13 @@ assert lltype.typeOf(size) == lltype.Signed return llmemory.raw_malloc(size) - def op_raw_realloc(self, ptr, size): + def op_raw_realloc_grow(self, addr, old_size, size): assert lltype.typeOf(size) == lltype.Signed - return llmemory.raw_realloc(llmemory.cast_ptr_to_adr(ptr), size) + return llmemory.raw_realloc_grow(addr, old_size, size) + + def op_raw_realloc_shrink(self, addr, old_size, size): + assert lltype.typeOf(size) == lltype.Signed + return llmemory.raw_realloc_shrink(addr, old_size, size) op_boehm_malloc = op_boehm_malloc_atomic = op_raw_malloc From fijal at codespeak.net Mon May 12 13:40:24 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 12 May 2008 13:40:24 +0200 (CEST) Subject: [pypy-svn] r54671 - in pypy/branch/hybrid-io/pypy/rpython/memory: gc gctransform Message-ID: <20080512114024.611CB49824B@codespeak.net> Author: fijal Date: Mon May 12 13:40:23 2008 New Revision: 54671 Modified: pypy/branch/hybrid-io/pypy/rpython/memory/gc/hybrid.py pypy/branch/hybrid-io/pypy/rpython/memory/gctransform/boehm.py pypy/branch/hybrid-io/pypy/rpython/memory/gctransform/framework.py pypy/branch/hybrid-io/pypy/rpython/memory/gctransform/transform.py Log: Implement resizable buffer on top of hybrid gc. Test seems to pass, but realloc ops are not implemented on top of C backend. Modified: pypy/branch/hybrid-io/pypy/rpython/memory/gc/hybrid.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/memory/gc/hybrid.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/memory/gc/hybrid.py Mon May 12 13:40:23 2008 @@ -10,6 +10,7 @@ from pypy.rpython.lltypesystem.lloperation import llop from pypy.rlib.debug import ll_assert from pypy.rlib.rarithmetic import ovfcheck +from pypy.rpython.lltypesystem import rffi # _______in the semispaces_________ ______external (non-moving)_____ # / \ / \ @@ -68,7 +69,6 @@ # number of calls to semispace_collect(): GENERATION3_COLLECT_THRESHOLD = 20 - class HybridGC(GenerationGC): """A two-generations semi-space GC like the GenerationGC, except that objects above a certain size are handled separately: @@ -76,6 +76,7 @@ """ first_unused_gcflag = _gcflag_next_bit prebuilt_gc_objects_are_static_roots = True + can_realloc = True # the following values override the default arguments of __init__ when # translating to a real backend. @@ -211,6 +212,29 @@ raise NotImplementedError("Not supported") return llmemory.cast_ptr_to_adr(gcref) + def realloc(self, ptr, newsize, const_size, itemsize, lengthofs, grow): + size_gc_header = self.size_gc_header() + addr = llmemory.cast_ptr_to_adr(ptr) + tid = self.get_type_id(addr) + tot_size = size_gc_header + const_size + newsize * itemsize + oldsize = (addr + lengthofs).signed[0] + old_tot_size = size_gc_header + const_size + oldsize * itemsize + source_addr = addr - size_gc_header + if grow: + result = llop.raw_realloc_grow(llmemory.Address, source_addr, + old_tot_size, tot_size) + else: + result = llop.raw_realloc_shrink(llmemory.Address, source_addr, + old_tot_size, tot_size) + if not result: + raise MemoryError() + if result != addr: + flags = self.GCFLAGS_FOR_NEW_EXTERNAL_OBJECTS | GCFLAG_UNVISITED + self.gen2_rawmalloced_objects.append(result) + self.init_gc_object(result, tid, flags) + (result + size_gc_header + lengthofs).signed[0] = newsize + return llmemory.cast_adr_to_ptr(result + size_gc_header, llmemory.GCREF) + def can_move(self, addr): tid = self.header(addr).tid return not (tid & GCFLAG_EXTERNAL) Modified: pypy/branch/hybrid-io/pypy/rpython/memory/gctransform/boehm.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/memory/gctransform/boehm.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/memory/gctransform/boehm.py Mon May 12 13:40:23 2008 @@ -64,7 +64,7 @@ return True def perform_realloc(self, hop, v_ptr, v_newlgt, c_const_size, c_item_size, - c_lengthofs): + c_lengthofs, c_grow): args = [self.realloc_ptr, v_ptr, v_newlgt, c_const_size, c_item_size, c_lengthofs] return hop.genop('direct_call', args, resulttype=llmemory.Address) Modified: pypy/branch/hybrid-io/pypy/rpython/memory/gctransform/framework.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/memory/gctransform/framework.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/memory/gctransform/framework.py Mon May 12 13:40:23 2008 @@ -284,6 +284,14 @@ else: self.malloc_varsize_nonmovable_ptr = None + if getattr(GCClass, 'realloc', False): + self.realloc_ptr = getfn( + GCClass.realloc.im_func, + [s_gc, s_gcref] + + [annmodel.SomeInteger(nonneg=True)] * 4 + + [annmodel.SomeBool()], + s_gcref) + if GCClass.moving_gc: self.id_ptr = getfn(GCClass.id.im_func, [s_gc, s_gcref], annmodel.SomeInteger(), @@ -508,6 +516,16 @@ def _can_realloc(self): return self.gcdata.gc.can_realloc + def perform_realloc(self, hop, v_ptr, v_newsize, c_const_size, + c_itemsize, c_lengthofs, c_grow): + vlist = [self.realloc_ptr, self.c_const_gc, v_ptr, v_newsize, + c_const_size, c_itemsize, c_lengthofs, c_grow] + livevars = self.push_roots(hop) + v_result = hop.genop('direct_call', vlist, + resulttype=llmemory.GCREF) + self.pop_roots(hop, livevars) + return v_result + def gct_gc__disable_finalizers(self, hop): # cannot collect() op = hop.spaceop Modified: pypy/branch/hybrid-io/pypy/rpython/memory/gctransform/transform.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/memory/gctransform/transform.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/memory/gctransform/transform.py Mon May 12 13:40:23 2008 @@ -539,6 +539,7 @@ def gct_malloc_resizable_buffer(self, hop): flags = hop.spaceop.args[1].value flags['varsize'] = True + flags['nonmovable'] = True flavor = flags['flavor'] assert flavor != 'cpy', "cannot malloc CPython objects directly" meth = getattr(self, 'gct_fv_%s_malloc_varsize' % flavor, None) @@ -548,14 +549,14 @@ def gct_resize_buffer(self, hop): op = hop.spaceop if self._can_realloc(): - self._gct_resize_buffer_realloc(hop, op.args[2]) + self._gct_resize_buffer_realloc(hop, op.args[2], True) else: self._gct_resize_buffer_no_realloc(hop, op.args[1]) def _can_realloc(self): return False - def _gct_resize_buffer_realloc(self, hop, v_newsize): + def _gct_resize_buffer_realloc(self, hop, v_newsize, grow=True): def intconst(c): return rmodel.inputconst(lltype.Signed, c) op = hop.spaceop flags = {'flavor':'gc', 'varsize': True} @@ -568,8 +569,10 @@ c_lengthofs = intconst(offset_to_length) v_ptr = op.args[0] + v_ptr = gen_cast(hop.llops, llmemory.GCREF, v_ptr) + c_grow = rmodel.inputconst(lltype.Bool, grow) v_raw = self.perform_realloc(hop, v_ptr, v_newsize, c_const_size, - c_item_size, c_lengthofs) + c_item_size, c_lengthofs, c_grow) hop.cast_result(v_raw) def _gct_resize_buffer_no_realloc(self, hop, v_lgt): @@ -603,7 +606,7 @@ def gct_finish_building_buffer(self, hop): op = hop.spaceop if self._can_realloc(): - return self._gct_resize_buffer_realloc(hop, op.args[1]) + return self._gct_resize_buffer_realloc(hop, op.args[1], False) else: return self._gct_resize_buffer_no_realloc(hop, op.args[1]) From fijal at codespeak.net Mon May 12 13:45:31 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 12 May 2008 13:45:31 +0200 (CEST) Subject: [pypy-svn] r54672 - pypy/branch/hybrid-io/pypy/translator/c/test Message-ID: <20080512114531.E624249824A@codespeak.net> Author: fijal Date: Mon May 12 13:45:29 2008 New Revision: 54672 Modified: pypy/branch/hybrid-io/pypy/translator/c/test/test_boehm.py Log: Test malloc_nonmovable on top of boehm as well Modified: pypy/branch/hybrid-io/pypy/translator/c/test/test_boehm.py ============================================================================== --- pypy/branch/hybrid-io/pypy/translator/c/test/test_boehm.py (original) +++ pypy/branch/hybrid-io/pypy/translator/c/test/test_boehm.py Mon May 12 13:45:29 2008 @@ -377,6 +377,23 @@ c_fn = self.getcompiled(fn, []) assert c_fn() == False + def test_malloc_nonmovable(self): + TP = lltype.GcArray(lltype.Char) + def func(): + try: + from pypy.rlib import rgc + a = rgc.malloc_nonmovable(TP, 3) + rgc.collect() + if a: + assert not rgc.can_move(a) + return 0 + return 1 + except Exception, e: + return 2 + + run = self.getcompiled(func) + assert run() == 0 + def test_resizable_buffer(self): from pypy.rpython.lltypesystem.rstr import STR from pypy.rpython.annlowlevel import hlstr From fijal at codespeak.net Mon May 12 14:02:30 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 12 May 2008 14:02:30 +0200 (CEST) Subject: [pypy-svn] r54673 - pypy/branch/hybrid-io/pypy/rpython Message-ID: <20080512120230.B71F7169FE1@codespeak.net> Author: fijal Date: Mon May 12 14:02:26 2008 New Revision: 54673 Modified: pypy/branch/hybrid-io/pypy/rpython/llinterp.py Log: forgotten cast Modified: pypy/branch/hybrid-io/pypy/rpython/llinterp.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/llinterp.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/llinterp.py Mon May 12 14:02:26 2008 @@ -770,7 +770,8 @@ def op_gc__enable_finalizers(self): self.heap.enable_finalizers() - def op_gc_can_move(self, addr): + def op_gc_can_move(self, ptr): + addr = llmemory.cast_ptr_to_adr(ptr) return self.heap.can_move(addr) def op_gc_free(self, addr): From fijal at codespeak.net Mon May 12 14:03:58 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 12 May 2008 14:03:58 +0200 (CEST) Subject: [pypy-svn] r54674 - pypy/branch/hybrid-io/pypy/translator/c/test Message-ID: <20080512120358.672EE16A05C@codespeak.net> Author: fijal Date: Mon May 12 14:03:57 2008 New Revision: 54674 Modified: pypy/branch/hybrid-io/pypy/translator/c/test/test_newgc.py Log: New tests here (skip for hybrid gc) Modified: pypy/branch/hybrid-io/pypy/translator/c/test/test_newgc.py ============================================================================== --- pypy/branch/hybrid-io/pypy/translator/c/test/test_newgc.py (original) +++ pypy/branch/hybrid-io/pypy/translator/c/test/test_newgc.py Mon May 12 14:03:57 2008 @@ -284,6 +284,8 @@ class TestUsingFramework(AbstractGCTestClass): gcpolicy = "marksweep" should_be_moving = False + GC_CAN_MOVE = False + GC_CANNOT_MALLOC_NONMOVABLE = False # interface for snippet.py large_tests_ok = True @@ -882,11 +884,54 @@ c_fn = self.getcompiled(f) assert c_fn() == 1 + + def test_can_move(self): + from pypy.rlib import rgc + class A: + pass + def fn(): + return rgc.can_move(A()) + c_fn = self.getcompiled(fn, []) + assert c_fn() == self.GC_CAN_MOVE + + def test_malloc_nonmovable(self): + TP = lltype.GcArray(lltype.Char) + def func(): + try: + from pypy.rlib import rgc + a = rgc.malloc_nonmovable(TP, 3) + rgc.collect() + if a: + assert not rgc.can_move(a) + return 0 + return 1 + except Exception, e: + return 2 + + run = self.getcompiled(func) + assert run() == self.GC_CANNOT_MALLOC_NONMOVABLE + + def test_resizable_buffer(self): + from pypy.rpython.lltypesystem.rstr import STR + from pypy.rpython.annlowlevel import hlstr + from pypy.rlib import rgc + + def f(): + ptr = rgc.resizable_buffer_of_shape(STR, 2) + ptr.chars[0] = 'a' + ptr = rgc.resize_buffer(ptr, 1, 200) + ptr.chars[1] = 'b' + return hlstr(rgc.finish_building_buffer(ptr, 2)) == "ab" + + run = self.getcompiled(f) + assert run() == True class TestSemiSpaceGC(TestUsingFramework, snippet.SemiSpaceGCTests): gcpolicy = "semispace" should_be_moving = True + GC_CAN_MOVE = True + GC_CANNOT_MALLOC_NONMOVABLE = True def test_many_ids(self): from pypy.rlib.objectmodel import compute_unique_id @@ -946,6 +991,10 @@ class TestHybridGC(TestGenerationalGC): gcpolicy = "hybrid" should_be_moving = True + GC_CANNOT_MALLOC_NONMOVABLE = False + + def test_resizable_buffer(self): + py.test.skip("segfaults") def test_gc_set_max_heap_size(self): py.test.skip("not implemented") From fijal at codespeak.net Mon May 12 14:04:35 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 12 May 2008 14:04:35 +0200 (CEST) Subject: [pypy-svn] r54675 - pypy/branch/hybrid-io/pypy/translator/c/src Message-ID: <20080512120435.A8F2B16A05C@codespeak.net> Author: fijal Date: Mon May 12 14:04:33 2008 New Revision: 54675 Modified: pypy/branch/hybrid-io/pypy/translator/c/src/mem.h Log: implement realloc ops Modified: pypy/branch/hybrid-io/pypy/translator/c/src/mem.h ============================================================================== --- pypy/branch/hybrid-io/pypy/translator/c/src/mem.h (original) +++ pypy/branch/hybrid-io/pypy/translator/c/src/mem.h Mon May 12 14:04:33 2008 @@ -77,6 +77,10 @@ #define OP_RAW_MALLOC_USAGE(size, r) r = size +#define OP_RAW_REALLOC_SHRINK(p, old_size, size, r) r = realloc((void*)p, size) + +#define OP_RAW_REALLOC_GROW(p, old_size, size, r) r = realloc((void*)p, size) + #ifdef MS_WINDOWS #define alloca _alloca #endif From bigdog at codespeak.net Mon May 12 14:38:02 2008 From: bigdog at codespeak.net (bigdog at codespeak.net) Date: Mon, 12 May 2008 14:38:02 +0200 (CEST) Subject: [pypy-svn] r54676 - pypy/dist/pypy/config Message-ID: <20080512123802.CA90249824B@codespeak.net> Author: bigdog Date: Mon May 12 14:37:59 2008 New Revision: 54676 Modified: pypy/dist/pypy/config/pypyoption.py Log: the bzr2 module correctly translates on windows, add to windows allworkingmodules list. This was the last of the allworkinglist modules. They are all now classified as: will never work, or broken. Modified: pypy/dist/pypy/config/pypyoption.py ============================================================================== --- pypy/dist/pypy/config/pypyoption.py (original) +++ pypy/dist/pypy/config/pypyoption.py Mon May 12 14:37:59 2008 @@ -45,8 +45,7 @@ # modules with unknown windows support # XXX what exactly is broken here? are the libs installed on the buildbots? del working_modules["zlib"] # MLS - Added 5/11/08 - broken - del working_modules["bz2"] # UNKNOWN State - needs validating - + module_dependencies = {} From bigdog at codespeak.net Mon May 12 15:47:57 2008 From: bigdog at codespeak.net (bigdog at codespeak.net) Date: Mon, 12 May 2008 15:47:57 +0200 (CEST) Subject: [pypy-svn] r54677 - in pypy/dist/pypy: config rlib Message-ID: <20080512134757.83014498001@codespeak.net> Author: bigdog Date: Mon May 12 15:47:54 2008 New Revision: 54677 Modified: pypy/dist/pypy/config/pypyoption.py pypy/dist/pypy/rlib/rzlib.py Log: add windows-specific option to zlib build rule, look for zlib rather the z. Activate zlib on windows allworking modules set Modified: pypy/dist/pypy/config/pypyoption.py ============================================================================== --- pypy/dist/pypy/config/pypyoption.py (original) +++ pypy/dist/pypy/config/pypyoption.py Mon May 12 15:47:54 2008 @@ -44,7 +44,6 @@ del working_modules["select"] # MLS - Added 5/11/08 - broken # modules with unknown windows support # XXX what exactly is broken here? are the libs installed on the buildbots? - del working_modules["zlib"] # MLS - Added 5/11/08 - broken Modified: pypy/dist/pypy/rlib/rzlib.py ============================================================================== --- pypy/dist/pypy/rlib/rzlib.py (original) +++ pypy/dist/pypy/rlib/rzlib.py Mon May 12 15:47:54 2008 @@ -4,7 +4,11 @@ from pypy.translator.tool.cbuild import ExternalCompilationInfo includes = ['zlib.h'] -libraries = ['z'] +if sys.platform == "win32": + libraries = ['zlib'] +else: + libraries = ['z'] + constantnames = ''' Z_OK Z_STREAM_ERROR Z_BUF_ERROR Z_MEM_ERROR Z_STREAM_END From bigdog at codespeak.net Mon May 12 16:43:30 2008 From: bigdog at codespeak.net (bigdog at codespeak.net) Date: Mon, 12 May 2008 16:43:30 +0200 (CEST) Subject: [pypy-svn] r54678 - pypy/dist/pypy/config Message-ID: <20080512144330.2EEF916A012@codespeak.net> Author: bigdog Date: Mon May 12 16:43:27 2008 New Revision: 54678 Modified: pypy/dist/pypy/config/pypyoption.py Log: Modified: pypy/dist/pypy/config/pypyoption.py ============================================================================== --- pypy/dist/pypy/config/pypyoption.py (original) +++ pypy/dist/pypy/config/pypyoption.py Mon May 12 16:43:27 2008 @@ -39,7 +39,7 @@ del working_modules["signal"] del working_modules["_rawffi"] # modules with broken windows support - del working_modules["mmap"] # MLS - Added 5/11/08 - broken + #del working_modules["mmap"] # MLS - Added 5/11/08 - broken del working_modules["_socket"] # MLS - Added 5/11/08 - broken del working_modules["select"] # MLS - Added 5/11/08 - broken # modules with unknown windows support From bigdog at codespeak.net Mon May 12 17:33:52 2008 From: bigdog at codespeak.net (bigdog at codespeak.net) Date: Mon, 12 May 2008 17:33:52 +0200 (CEST) Subject: [pypy-svn] r54679 - pypy/dist/pypy/config Message-ID: <20080512153352.BAEEE16A19B@codespeak.net> Author: bigdog Date: Mon May 12 17:33:50 2008 New Revision: 54679 Modified: pypy/dist/pypy/config/pypyoption.py Log: Commit changes for buildbot to pick up. No system changes expected Modified: pypy/dist/pypy/config/pypyoption.py ============================================================================== --- pypy/dist/pypy/config/pypyoption.py (original) +++ pypy/dist/pypy/config/pypyoption.py Mon May 12 17:33:50 2008 @@ -39,7 +39,7 @@ del working_modules["signal"] del working_modules["_rawffi"] # modules with broken windows support - #del working_modules["mmap"] # MLS - Added 5/11/08 - broken + del working_modules["mmap"] # MLS - Added 5/11/08 - broken del working_modules["_socket"] # MLS - Added 5/11/08 - broken del working_modules["select"] # MLS - Added 5/11/08 - broken # modules with unknown windows support From bigdog at codespeak.net Mon May 12 18:05:41 2008 From: bigdog at codespeak.net (bigdog at codespeak.net) Date: Mon, 12 May 2008 18:05:41 +0200 (CEST) Subject: [pypy-svn] r54680 - pypy/dist/pypy/config Message-ID: <20080512160541.6956D169E9B@codespeak.net> Author: bigdog Date: Mon May 12 18:05:38 2008 New Revision: 54680 Modified: pypy/dist/pypy/config/pypyoption.py Log: remove zlib until it successfully builds on buildslave. Link issue Modified: pypy/dist/pypy/config/pypyoption.py ============================================================================== --- pypy/dist/pypy/config/pypyoption.py (original) +++ pypy/dist/pypy/config/pypyoption.py Mon May 12 18:05:38 2008 @@ -39,6 +39,8 @@ del working_modules["signal"] del working_modules["_rawffi"] # modules with broken windows support + del working_modules["zlib"] # MLS - Added 5/11/08 - link issue + del working_modules["mmap"] # MLS - Added 5/11/08 - broken del working_modules["_socket"] # MLS - Added 5/11/08 - broken del working_modules["select"] # MLS - Added 5/11/08 - broken From bigdog at codespeak.net Mon May 12 18:13:59 2008 From: bigdog at codespeak.net (bigdog at codespeak.net) Date: Mon, 12 May 2008 18:13:59 +0200 (CEST) Subject: [pypy-svn] r54681 - pypy/dist/pypy/config Message-ID: <20080512161359.A4EC8169EC8@codespeak.net> Author: bigdog Date: Mon May 12 18:13:58 2008 New Revision: 54681 Modified: pypy/dist/pypy/config/pypyoption.py Log: buildbot test Modified: pypy/dist/pypy/config/pypyoption.py ============================================================================== --- pypy/dist/pypy/config/pypyoption.py (original) +++ pypy/dist/pypy/config/pypyoption.py Mon May 12 18:13:58 2008 @@ -39,7 +39,7 @@ del working_modules["signal"] del working_modules["_rawffi"] # modules with broken windows support - del working_modules["zlib"] # MLS - Added 5/11/08 - link issue + #del working_modules["zlib"] # MLS - Added 5/11/08 - link issue del working_modules["mmap"] # MLS - Added 5/11/08 - broken del working_modules["_socket"] # MLS - Added 5/11/08 - broken From bigdog at codespeak.net Mon May 12 19:12:16 2008 From: bigdog at codespeak.net (bigdog at codespeak.net) Date: Mon, 12 May 2008 19:12:16 +0200 (CEST) Subject: [pypy-svn] r54682 - pypy/dist/pypy/config Message-ID: <20080512171216.CA946498250@codespeak.net> Author: bigdog Date: Mon May 12 19:12:13 2008 New Revision: 54682 Modified: pypy/dist/pypy/config/pypyoption.py Log: restore code for windows all working modules Modified: pypy/dist/pypy/config/pypyoption.py ============================================================================== --- pypy/dist/pypy/config/pypyoption.py (original) +++ pypy/dist/pypy/config/pypyoption.py Mon May 12 19:12:13 2008 @@ -39,7 +39,7 @@ del working_modules["signal"] del working_modules["_rawffi"] # modules with broken windows support - #del working_modules["zlib"] # MLS - Added 5/11/08 - link issue + del working_modules["zlib"] # MLS - Added 5/11/08 - link issue del working_modules["mmap"] # MLS - Added 5/11/08 - broken del working_modules["_socket"] # MLS - Added 5/11/08 - broken From antocuni at codespeak.net Mon May 12 20:30:13 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 12 May 2008 20:30:13 +0200 (CEST) Subject: [pypy-svn] r54683 - pypy/extradoc/sprintinfo/berlin-2008 Message-ID: <20080512183013.78263498250@codespeak.net> Author: antocuni Date: Mon May 12 20:30:10 2008 New Revision: 54683 Modified: pypy/extradoc/sprintinfo/berlin-2008/people.txt Log: my hotel Modified: pypy/extradoc/sprintinfo/berlin-2008/people.txt ============================================================================== --- pypy/extradoc/sprintinfo/berlin-2008/people.txt (original) +++ pypy/extradoc/sprintinfo/berlin-2008/people.txt Mon May 12 20:30:10 2008 @@ -17,7 +17,7 @@ Samuele Pedroni 16-21 Hotel Klassik Berlin Armin Rigo 14-22(noon) private, thanks Stephan Carl Friedrich Bolz 14-22 Die Fabrik -Antonio Cuni 19-24 ? +Antonio Cuni 19-24 A&O Hotel Mitte ==================== ============== ======================= People on the following list were present at previous sprints: @@ -41,7 +41,6 @@ Niko Matsakis ? ? Alexander Schremmer ? ? Anders Chrigstroem ? ? -Samuele Pedroni ? ? Michael Hudson ? ? Niko Matsakis ? ? Eric van Riet Paap ? ? @@ -52,7 +51,6 @@ Leonardo Santagada ? ? Alexandre Fayolle ? ? Sylvain Th?nault ? ? -Armin Rigo ? ? Toby Watson ? ? Paul deGrandis ? ? ==================== ============== ===================== From bigdog at codespeak.net Mon May 12 21:01:23 2008 From: bigdog at codespeak.net (bigdog at codespeak.net) Date: Mon, 12 May 2008 21:01:23 +0200 (CEST) Subject: [pypy-svn] r54684 - pypy/dist/pypy/config Message-ID: <20080512190123.241A149823F@codespeak.net> Author: bigdog Date: Mon May 12 21:01:21 2008 New Revision: 54684 Modified: pypy/dist/pypy/config/pypyoption.py Log: activate zlib during windows allworking modules translations, buildbot now correctly translates allworkingmodules with zlib Modified: pypy/dist/pypy/config/pypyoption.py ============================================================================== --- pypy/dist/pypy/config/pypyoption.py (original) +++ pypy/dist/pypy/config/pypyoption.py Mon May 12 21:01:21 2008 @@ -39,14 +39,10 @@ del working_modules["signal"] del working_modules["_rawffi"] # modules with broken windows support - del working_modules["zlib"] # MLS - Added 5/11/08 - link issue - del working_modules["mmap"] # MLS - Added 5/11/08 - broken del working_modules["_socket"] # MLS - Added 5/11/08 - broken del working_modules["select"] # MLS - Added 5/11/08 - broken - # modules with unknown windows support - # XXX what exactly is broken here? are the libs installed on the buildbots? - + module_dependencies = {} From bgola at codespeak.net Tue May 13 00:16:32 2008 From: bgola at codespeak.net (bgola at codespeak.net) Date: Tue, 13 May 2008 00:16:32 +0200 (CEST) Subject: [pypy-svn] r54692 - in pypy/branch/2.5-features/pypy/interpreter/pyparser: . test Message-ID: <20080512221632.178E149824D@codespeak.net> Author: bgola Date: Tue May 13 00:16:32 2008 New Revision: 54692 Modified: pypy/branch/2.5-features/pypy/interpreter/pyparser/astbuilder.py pypy/branch/2.5-features/pypy/interpreter/pyparser/test/expressions.py Log: supporting the class A(): pass 2.5 syntax Modified: pypy/branch/2.5-features/pypy/interpreter/pyparser/astbuilder.py ============================================================================== --- pypy/branch/2.5-features/pypy/interpreter/pyparser/astbuilder.py (original) +++ pypy/branch/2.5-features/pypy/interpreter/pyparser/astbuilder.py Tue May 13 00:16:32 2008 @@ -632,16 +632,19 @@ def build_classdef(builder, nb): - """classdef: 'class' NAME ['(' testlist ')'] ':' suite""" + """classdef: 'class' NAME ['(' [testlist] ')'] ':' suite""" atoms = get_atoms(builder, nb) lineno = atoms[0].lineno l = len(atoms) classname_token = atoms[1] assert isinstance(classname_token, TokenObject) classname = classname_token.get_value() - if l == 4: + if l == 4: # class NAME: basenames = [] body = atoms[3] + elif l == 6: # class NAME(): # 2.5 + basenames = [] + body = atoms[5] else: assert l == 7 basenames = [] Modified: pypy/branch/2.5-features/pypy/interpreter/pyparser/test/expressions.py ============================================================================== --- pypy/branch/2.5-features/pypy/interpreter/pyparser/test/expressions.py (original) +++ pypy/branch/2.5-features/pypy/interpreter/pyparser/test/expressions.py Tue May 13 00:16:32 2008 @@ -361,6 +361,9 @@ one_stmt_classdefs = [ "class Pdb(bdb.Bdb, cmd.Cmd): pass", + "class A(): pass", + "class A: pass", + "class A)(: x", ] docstrings = [ From fijal at codespeak.net Tue May 13 00:43:48 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 13 May 2008 00:43:48 +0200 (CEST) Subject: [pypy-svn] r54693 - pypy/dist/lib-python/modified-2.4.1 Message-ID: <20080512224348.4C82249823E@codespeak.net> Author: fijal Date: Tue May 13 00:43:46 2008 New Revision: 54693 Removed: pypy/dist/lib-python/modified-2.4.1/site.py Log: (A candidate for revert) It seems that we no longer need modified site.py and it prevents ipython from running. From fijal at codespeak.net Tue May 13 13:22:06 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 13 May 2008 13:22:06 +0200 (CEST) Subject: [pypy-svn] r54694 - in pypy/dist/pypy/lib: _ctypes app_test/ctypes_tests Message-ID: <20080513112206.7EE7D169F9B@codespeak.net> Author: fijal Date: Tue May 13 13:22:03 2008 New Revision: 54694 Modified: pypy/dist/pypy/lib/_ctypes/primitive.py pypy/dist/pypy/lib/app_test/ctypes_tests/_ctypes_test.c pypy/dist/pypy/lib/app_test/ctypes_tests/test_callbacks.py Log: somewhat lame support for pyobjs. Leak memory right now. Modified: pypy/dist/pypy/lib/_ctypes/primitive.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/primitive.py (original) +++ pypy/dist/pypy/lib/_ctypes/primitive.py Tue May 13 13:22:03 2008 @@ -1,4 +1,5 @@ import _rawffi +import weakref SIMPLE_TYPE_CHARS = "cbBhHiIlLdfuzZqQPXOv" @@ -34,6 +35,20 @@ DEFAULT_VALUE = object() +class GlobalPyobjContainer(object): + def __init__(self): + self.objs = [] + + def add(self, obj): + num = len(self.objs) + self.objs.append(weakref.ref(obj)) + return num + + def get(self, num): + return self.objs[num]() + +pyobj_container = GlobalPyobjContainer() + def generic_xxx_p_from_param(self, value): from _ctypes import Array, _Pointer if value is None: @@ -182,6 +197,14 @@ return self._buffer[0] result.value = property(_getvalue, _setvalue) + elif tp == 'O': + def _setvalue(self, val): + num = pyobj_container.add(val) + self._buffer[0] = num + def _getvalue(self): + return pyobj_container.get(self._buffer[0]) + result.value = property(_getvalue, _setvalue) + return result from_address = cdata_from_address Modified: pypy/dist/pypy/lib/app_test/ctypes_tests/_ctypes_test.c ============================================================================== --- pypy/dist/pypy/lib/app_test/ctypes_tests/_ctypes_test.c (original) +++ pypy/dist/pypy/lib/app_test/ctypes_tests/_ctypes_test.c Tue May 13 13:22:03 2008 @@ -160,6 +160,11 @@ return (*func)(table); } +EXPORT(int) _testfunc_callback_opaque(int (*func)(void*), void* arg) +{ + return (*func)(arg); +} + #ifdef HAVE_LONG_LONG EXPORT(LONG_LONG) _testfunc_q_bhilfdq(signed char b, short h, int i, long l, float f, double d, LONG_LONG q) @@ -526,3 +531,4 @@ inp.y = inp.x * 10000; return inp; } + Modified: pypy/dist/pypy/lib/app_test/ctypes_tests/test_callbacks.py ============================================================================== --- pypy/dist/pypy/lib/app_test/ctypes_tests/test_callbacks.py (original) +++ pypy/dist/pypy/lib/app_test/ctypes_tests/test_callbacks.py Tue May 13 13:22:03 2008 @@ -191,3 +191,18 @@ assert res == [1,2,3,4,5] + def test_pyobject_as_opaque(self): + import conftest + _ctypes_test = str(conftest.sofile) + dll = CDLL(_ctypes_test) + + def callback(arg): + return arg() + + CTP = CFUNCTYPE(c_int, py_object) + cfunc = dll._testfunc_callback_opaque + cfunc.argtypes = [CTP, py_object] + cfunc.restype = c_int + res = cfunc(CTP(callback), lambda : 3) + assert res == 3 + From fijal at codespeak.net Tue May 13 15:00:59 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 13 May 2008 15:00:59 +0200 (CEST) Subject: [pypy-svn] r54696 - pypy/dist/lib-python/modified-2.4.1 Message-ID: <20080513130059.55FAB16A1D3@codespeak.net> Author: fijal Date: Tue May 13 15:00:55 2008 New Revision: 54696 Added: pypy/dist/lib-python/modified-2.4.1/site.py (contents, props changed) Log: Re-create removed site.py from modified. Added: pypy/dist/lib-python/modified-2.4.1/site.py ============================================================================== --- (empty file) +++ pypy/dist/lib-python/modified-2.4.1/site.py Tue May 13 15:00:55 2008 @@ -0,0 +1,418 @@ +"""Append module search paths for third-party packages to sys.path. + +**************************************************************** +* This module is automatically imported during initialization. * +**************************************************************** + +In earlier versions of Python (up to 1.5a3), scripts or modules that +needed to use site-specific modules would place ``import site'' +somewhere near the top of their code. Because of the automatic +import, this is no longer necessary (but code that does it still +works). + +This will append site-specific paths to the module search path. On +Unix, it starts with sys.prefix and sys.exec_prefix (if different) and +appends lib/python/site-packages as well as lib/site-python. +On other platforms (mainly Mac and Windows), it uses just sys.prefix +(and sys.exec_prefix, if different, but this is unlikely). The +resulting directories, if they exist, are appended to sys.path, and +also inspected for path configuration files. + +A path configuration file is a file whose name has the form +.pth; its contents are additional directories (one per line) +to be added to sys.path. Non-existing directories (or +non-directories) are never added to sys.path; no directory is added to +sys.path more than once. Blank lines and lines beginning with +'#' are skipped. Lines starting with 'import' are executed. + +For example, suppose sys.prefix and sys.exec_prefix are set to +/usr/local and there is a directory /usr/local/lib/python1.5/site-packages +with three subdirectories, foo, bar and spam, and two path +configuration files, foo.pth and bar.pth. Assume foo.pth contains the +following: + + # foo package configuration + foo + bar + bletch + +and bar.pth contains: + + # bar package configuration + bar + +Then the following directories are added to sys.path, in this order: + + /usr/local/lib/python1.5/site-packages/bar + /usr/local/lib/python1.5/site-packages/foo + +Note that bletch is omitted because it doesn't exist; bar precedes foo +because bar.pth comes alphabetically before foo.pth; and spam is +omitted because it is not mentioned in either path configuration file. + +After these path manipulations, an attempt is made to import a module +named sitecustomize, which can perform arbitrary additional +site-specific customizations. If this import fails with an +ImportError exception, it is silently ignored. + +""" + +import sys +import os +import __builtin__ + + +def makepath(*paths): + dir = os.path.abspath(os.path.join(*paths)) + return dir, os.path.normcase(dir) + +def abs__file__(): + """Set all module' __file__ attribute to an absolute path""" + for m in sys.modules.values(): + try: + prev = m.__file__ + new = os.path.abspath(m.__file__) + if prev != new: + m.__file__ = new + except AttributeError: + continue + +def removeduppaths(): + """ Remove duplicate entries from sys.path along with making them + absolute""" + # This ensures that the initial path provided by the interpreter contains + # only absolute pathnames, even if we're running from the build directory. + L = [] + known_paths = set() + for dir in sys.path: + # Filter out duplicate paths (on case-insensitive file systems also + # if they only differ in case); turn relative paths into absolute + # paths. + dir, dircase = makepath(dir) + if not dircase in known_paths: + L.append(dir) + known_paths.add(dircase) + sys.path[:] = L + return known_paths + +# XXX This should not be part of site.py, since it is needed even when +# using the -S option for Python. See http://www.python.org/sf/586680 +def addbuilddir(): + """Append ./build/lib. in case we're running in the build dir + (especially for Guido :-)""" + from distutils.util import get_platform + s = "build/lib.%s-%.3s" % (get_platform(), sys.version) + s = os.path.join(os.path.dirname(sys.path[-1]), s) + sys.path.append(s) + +def _init_pathinfo(): + """Return a set containing all existing directory entries from sys.path""" + d = set() + for dir in sys.path: + try: + if os.path.isdir(dir): + dir, dircase = makepath(dir) + d.add(dircase) + except TypeError: + continue + return d + +def addpackage(sitedir, name, known_paths): + """Add a new path to known_paths by combining sitedir and 'name' or execute + sitedir if it starts with 'import'""" + if known_paths is None: + _init_pathinfo() + reset = 1 + else: + reset = 0 + fullname = os.path.join(sitedir, name) + try: + f = open(fullname, "rU") + except IOError: + return + try: + for line in f: + if line.startswith("#"): + continue + if line.startswith("import"): + exec line + continue + line = line.rstrip() + dir, dircase = makepath(sitedir, line) + if not dircase in known_paths and os.path.exists(dir): + sys.path.append(dir) + known_paths.add(dircase) + finally: + f.close() + if reset: + known_paths = None + return known_paths + +def addsitedir(sitedir, known_paths=None): + """Add 'sitedir' argument to sys.path if missing and handle .pth files in + 'sitedir'""" + if known_paths is None: + known_paths = _init_pathinfo() + reset = 1 + else: + reset = 0 + sitedir, sitedircase = makepath(sitedir) + if not sitedircase in known_paths: + sys.path.append(sitedir) # Add path component + try: + names = os.listdir(sitedir) + except os.error: + return + names.sort() + for name in names: + if name.endswith(os.extsep + "pth"): + addpackage(sitedir, name, known_paths) + if reset: + known_paths = None + return known_paths + +def addsitepackages(known_paths): + """Add site-packages (and possibly site-python) to sys.path""" + prefixes = [sys.prefix] + if sys.exec_prefix != sys.prefix: + prefixes.append(sys.exec_prefix) + for prefix in prefixes: + if prefix: + if sys.platform in ('os2emx', 'riscos'): + sitedirs = [os.path.join(prefix, "Lib", "site-packages")] + elif os.sep == '/': + sitedirs = [os.path.join(prefix, + "lib", + "python" + sys.version[:3], + "site-packages"), + os.path.join(prefix, "lib", "site-python")] + else: + sitedirs = [prefix, os.path.join(prefix, "lib", "site-packages")] + if sys.platform == 'darwin': + # for framework builds *only* we add the standard Apple + # locations. Currently only per-user, but /Library and + # /Network/Library could be added too + if 'Python.framework' in prefix: + home = os.environ.get('HOME') + if home: + sitedirs.append( + os.path.join(home, + 'Library', + 'Python', + sys.version[:3], + 'site-packages')) + for sitedir in sitedirs: + if os.path.isdir(sitedir): + addsitedir(sitedir, known_paths) + return None + + +def setBEGINLIBPATH(): + """The OS/2 EMX port has optional extension modules that do double duty + as DLLs (and must use the .DLL file extension) for other extensions. + The library search path needs to be amended so these will be found + during module import. Use BEGINLIBPATH so that these are at the start + of the library search path. + + """ + dllpath = os.path.join(sys.prefix, "Lib", "lib-dynload") + libpath = os.environ['BEGINLIBPATH'].split(';') + if libpath[-1]: + libpath.append(dllpath) + else: + libpath[-1] = dllpath + os.environ['BEGINLIBPATH'] = ';'.join(libpath) + + +def setquit(): + """Define new built-ins 'quit' and 'exit'. + These are simply strings that display a hint on how to exit. + + """ + if os.sep == ':': + exit = 'Use Cmd-Q to quit.' + elif os.sep == '\\': + exit = 'Use Ctrl-Z plus Return to exit.' + else: + exit = 'Use Ctrl-D (i.e. EOF) to exit.' + __builtin__.quit = __builtin__.exit = exit + + +class _Printer(object): + """interactive prompt objects for printing the license text, a list of + contributors and the copyright notice.""" + + MAXLINES = 23 + + def __init__(self, name, data, files=(), dirs=()): + self.__name = name + self.__data = data + self.__files = files + self.__dirs = dirs + self.__lines = None + + def __setup(self): + if self.__lines: + return + data = None + for dir in self.__dirs: + for filename in self.__files: + filename = os.path.join(dir, filename) + try: + fp = file(filename, "rU") + data = fp.read() + fp.close() + break + except IOError: + pass + if data: + break + if not data: + data = self.__data + self.__lines = data.split('\n') + self.__linecnt = len(self.__lines) + + def __repr__(self): + self.__setup() + if len(self.__lines) <= self.MAXLINES: + return "\n".join(self.__lines) + else: + return "Type %s() to see the full %s text" % ((self.__name,)*2) + + def __call__(self): + self.__setup() + prompt = 'Hit Return for more, or q (and Return) to quit: ' + lineno = 0 + while 1: + try: + for i in range(lineno, lineno + self.MAXLINES): + print self.__lines[i] + except IndexError: + break + else: + lineno += self.MAXLINES + key = None + while key is None: + key = raw_input(prompt) + if key not in ('', 'q'): + key = None + if key == 'q': + break + +##def setcopyright(): +## """Set 'copyright' and 'credits' in __builtin__""" +## __builtin__.copyright = _Printer("copyright", sys.copyright) +## if sys.platform[:4] == 'java': +## __builtin__.credits = _Printer( +## "credits", +## "Jython is maintained by the Jython developers (www.jython.org).") +## else: +## __builtin__.credits = _Printer("credits", """\ +## Thanks to CWI, CNRI, BeOpen.com, Zope Corporation and a cast of thousands +## for supporting Python development. See www.python.org for more information.""") +## here = os.path.dirname(os.__file__) +## __builtin__.license = _Printer( +## "license", "See http://www.python.org/%.3s/license.html" % sys.version, +## ["LICENSE.txt", "LICENSE"], +## [os.path.join(here, os.pardir), here, os.curdir]) + +def setcopyright(): + # XXX this is the PyPy-specific version. Should be unified with the above. + __builtin__.credits = _Printer( + "credits", + "PyPy is maintained by the PyPy developers: http://codespeak.net/pypy") + __builtin__.license = _Printer( + "license", + "See http://codespeak.net/svn/pypy/dist/LICENSE") + + +class _Helper(object): + """Define the built-in 'help'. + This is a wrapper around pydoc.help (with a twist). + + """ + + def __repr__(self): + return "Type help() for interactive help, " \ + "or help(object) for help about object." + def __call__(self, *args, **kwds): + import pydoc + return pydoc.help(*args, **kwds) + +def sethelper(): + __builtin__.help = _Helper() + +def aliasmbcs(): + """On Windows, some default encodings are not provided by Python, + while they are always available as "mbcs" in each locale. Make + them usable by aliasing to "mbcs" in such a case.""" + if sys.platform == 'win32': + import locale, codecs + enc = locale.getdefaultlocale()[1] + if enc is not None and enc.startswith('cp'): # "cp***" ? + try: + codecs.lookup(enc) + except LookupError: + import encodings + encodings._cache[enc] = encodings._unknown + encodings.aliases.aliases[enc] = 'mbcs' + +def setencoding(): + """Set the string encoding used by the Unicode implementation. The + default is 'ascii', but if you're willing to experiment, you can + change this.""" + encoding = "ascii" # Default value set by _PyUnicode_Init() + if 0: + # Enable to support locale aware default string encodings. + import locale + loc = locale.getdefaultlocale() + if loc[1]: + encoding = loc[1] + if 0: + # Enable to switch off string to Unicode coercion and implicit + # Unicode to string conversion. + encoding = "undefined" + if encoding != "ascii": + # On Non-Unicode builds this will raise an AttributeError... + sys.setdefaultencoding(encoding) # Needs Python Unicode build ! + + +def execsitecustomize(): + """Run custom site specific code, if available.""" + try: + import sitecustomize + except ImportError: + pass + + +def main(): + abs__file__() + paths_in_sys = removeduppaths() + if (os.name == "posix" and sys.path and + os.path.basename(sys.path[-1]) == "Modules"): + addbuilddir() + paths_in_sys = addsitepackages(paths_in_sys) + if sys.platform == 'os2emx': + setBEGINLIBPATH() + setquit() + setcopyright() + sethelper() + aliasmbcs() + setencoding() + execsitecustomize() + # Remove sys.setdefaultencoding() so that users cannot change the + # encoding after initialization. The test for presence is needed when + # this module is run as a script, because this code is executed twice. + if hasattr(sys, "setdefaultencoding"): + del sys.setdefaultencoding + +main() + +def _test(): + print "sys.path = [" + for dir in sys.path: + print " %r," % (dir,) + print "]" + +if __name__ == '__main__': + _test() From fijal at codespeak.net Tue May 13 15:01:43 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 13 May 2008 15:01:43 +0200 (CEST) Subject: [pypy-svn] r54697 - pypy/dist/lib-python/modified-2.4.1 Message-ID: <20080513130143.407B016A1D4@codespeak.net> Author: fijal Date: Tue May 13 15:01:41 2008 New Revision: 54697 Modified: pypy/dist/lib-python/modified-2.4.1/site.py Log: instantiate copyright as well Modified: pypy/dist/lib-python/modified-2.4.1/site.py ============================================================================== --- pypy/dist/lib-python/modified-2.4.1/site.py (original) +++ pypy/dist/lib-python/modified-2.4.1/site.py Tue May 13 15:01:41 2008 @@ -324,7 +324,7 @@ __builtin__.license = _Printer( "license", "See http://codespeak.net/svn/pypy/dist/LICENSE") - + __builtin__.copyright = _Printer('copyright', sys.copyright) class _Helper(object): """Define the built-in 'help'. From fijal at codespeak.net Tue May 13 15:06:56 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 13 May 2008 15:06:56 +0200 (CEST) Subject: [pypy-svn] r54698 - pypy/dist/lib-python/modified-2.4.1 Message-ID: <20080513130656.01F6316A1DF@codespeak.net> Author: fijal Date: Tue May 13 15:06:55 2008 New Revision: 54698 Added: pypy/dist/lib-python/modified-2.4.1/site.py - copied unchanged from r54692, pypy/dist/lib-python/modified-2.4.1/site.py Log: Properly revert site.py From fijal at codespeak.net Tue May 13 15:10:05 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 13 May 2008 15:10:05 +0200 (CEST) Subject: [pypy-svn] r54699 - pypy/dist/lib-python/modified-2.4.1 Message-ID: <20080513131005.6295216A1DF@codespeak.net> Author: fijal Date: Tue May 13 15:10:04 2008 New Revision: 54699 Modified: pypy/dist/lib-python/modified-2.4.1/site.py Log: Overwrite __builtin__.copyright as well with _Printer Modified: pypy/dist/lib-python/modified-2.4.1/site.py ============================================================================== --- pypy/dist/lib-python/modified-2.4.1/site.py (original) +++ pypy/dist/lib-python/modified-2.4.1/site.py Tue May 13 15:10:04 2008 @@ -324,7 +324,7 @@ __builtin__.license = _Printer( "license", "See http://codespeak.net/svn/pypy/dist/LICENSE") - + __builtin__.copyright = _Printer('copyright', sys.copyright) class _Helper(object): """Define the built-in 'help'. From fijal at codespeak.net Tue May 13 15:13:05 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 13 May 2008 15:13:05 +0200 (CEST) Subject: [pypy-svn] r54700 - pypy/dist/pypy/module/__builtin__ Message-ID: <20080513131305.7A8A1498262@codespeak.net> Author: fijal Date: Tue May 13 15:13:04 2008 New Revision: 54700 Modified: pypy/dist/pypy/module/__builtin__/app_help.py Log: update a year Modified: pypy/dist/pypy/module/__builtin__/app_help.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/app_help.py (original) +++ pypy/dist/pypy/module/__builtin__/app_help.py Tue May 13 15:13:04 2008 @@ -10,7 +10,7 @@ exit = "Use Ctrl-D (i.e. EOF) to exit." def copyright(): - print 'Copyright 2003-2007 PyPy development team.\nAll rights reserved.\nFor further information see http://www.codespeak.net/pypy.\nSome materials may have a different copyright.\nIn these cases, this is explicitly noted in the source code file.' + print 'Copyright 2003-2008 PyPy development team.\nAll rights reserved.\nFor further information see http://www.codespeak.net/pypy.\nSome materials may have a different copyright.\nIn these cases, this is explicitly noted in the source code file.' def license(): print \ From fijal at codespeak.net Tue May 13 15:13:30 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 13 May 2008 15:13:30 +0200 (CEST) Subject: [pypy-svn] r54701 - pypy/dist/pypy/module/sys Message-ID: <20080513131330.ED05849825D@codespeak.net> Author: fijal Date: Tue May 13 15:13:29 2008 New Revision: 54701 Modified: pypy/dist/pypy/module/sys/__init__.py pypy/dist/pypy/module/sys/app.py Log: Make copyright message a bit more verbose (same as printed by __builtin__.copyright) Modified: pypy/dist/pypy/module/sys/__init__.py ============================================================================== --- pypy/dist/pypy/module/sys/__init__.py (original) +++ pypy/dist/pypy/module/sys/__init__.py Tue May 13 15:13:29 2008 @@ -50,7 +50,6 @@ 'call_tracing' : 'vm.call_tracing', 'executable' : 'space.wrap("py.py")', - 'copyright' : 'space.wrap("MIT-License")', 'api_version' : 'version.get_api_version(space)', 'version_info' : 'version.get_version_info(space)', 'version' : 'version.get_version(space)', @@ -79,6 +78,7 @@ 'exitfunc' : 'app.exitfunc', 'getfilesystemencoding' : 'app.getfilesystemencoding', 'callstats' : 'app.callstats', + 'copyright' : 'app.copyright_str', } def setbuiltinmodule(self, w_module, name): Modified: pypy/dist/pypy/module/sys/app.py ============================================================================== --- pypy/dist/pypy/module/sys/app.py (original) +++ pypy/dist/pypy/module/sys/app.py Tue May 13 15:13:29 2008 @@ -42,3 +42,10 @@ """Not implemented.""" return None +copyright_str = """ +Copyright 2003-2008 PyPy development team. +All rights reserved. +For further information see http://www.codespeak.net/pypy. +Some materials may have a different copyright. +In these cases, this is explicitly noted in the source code file. +""" From fijal at codespeak.net Tue May 13 17:00:40 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 13 May 2008 17:00:40 +0200 (CEST) Subject: [pypy-svn] r54704 - in pypy/branch/hybrid-io/pypy/translator/c: src test Message-ID: <20080513150040.8B0B116A1B4@codespeak.net> Author: fijal Date: Tue May 13 17:00:33 2008 New Revision: 54704 Modified: pypy/branch/hybrid-io/pypy/translator/c/src/mem.h pypy/branch/hybrid-io/pypy/translator/c/test/test_newgc.py Log: wrong realloc. test passes now :) Modified: pypy/branch/hybrid-io/pypy/translator/c/src/mem.h ============================================================================== --- pypy/branch/hybrid-io/pypy/translator/c/src/mem.h (original) +++ pypy/branch/hybrid-io/pypy/translator/c/src/mem.h Tue May 13 17:00:33 2008 @@ -77,9 +77,9 @@ #define OP_RAW_MALLOC_USAGE(size, r) r = size -#define OP_RAW_REALLOC_SHRINK(p, old_size, size, r) r = realloc((void*)p, size) +#define OP_RAW_REALLOC_SHRINK(p, old_size, size, r) r = PyObject_Realloc((void*)p, size) -#define OP_RAW_REALLOC_GROW(p, old_size, size, r) r = realloc((void*)p, size) +#define OP_RAW_REALLOC_GROW(p, old_size, size, r) r = PyObject_Realloc((void*)p, size) #ifdef MS_WINDOWS #define alloca _alloca Modified: pypy/branch/hybrid-io/pypy/translator/c/test/test_newgc.py ============================================================================== --- pypy/branch/hybrid-io/pypy/translator/c/test/test_newgc.py (original) +++ pypy/branch/hybrid-io/pypy/translator/c/test/test_newgc.py Tue May 13 17:00:33 2008 @@ -993,8 +993,5 @@ should_be_moving = True GC_CANNOT_MALLOC_NONMOVABLE = False - def test_resizable_buffer(self): - py.test.skip("segfaults") - def test_gc_set_max_heap_size(self): py.test.skip("not implemented") From fijal at codespeak.net Tue May 13 17:07:46 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 13 May 2008 17:07:46 +0200 (CEST) Subject: [pypy-svn] r54706 - pypy/branch/hybrid-io/pypy/objspace/std Message-ID: <20080513150746.998A716A1B5@codespeak.net> Author: fijal Date: Tue May 13 17:07:44 2008 New Revision: 54706 Modified: pypy/branch/hybrid-io/pypy/objspace/std/stringobject.py Log: There is an assumption that init_size needs to be constant. There is no good reason for that, but fix translation. Modified: pypy/branch/hybrid-io/pypy/objspace/std/stringobject.py ============================================================================== --- pypy/branch/hybrid-io/pypy/objspace/std/stringobject.py (original) +++ pypy/branch/hybrid-io/pypy/objspace/std/stringobject.py Tue May 13 17:07:44 2008 @@ -861,7 +861,7 @@ def repr__String(space, w_str): s = w_str._value - buf = StringBuilder(len(s) + 10) + buf = StringBuilder(50) # XXX this needs to be constant, fix quote = "'" if quote in s and '"' not in s: From arigo at codespeak.net Tue May 13 19:04:10 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 13 May 2008 19:04:10 +0200 (CEST) Subject: [pypy-svn] r54710 - in pypy/dist/pypy: interpreter module/_weakref module/_weakref/test Message-ID: <20080513170410.2928516A0B5@codespeak.net> Author: arigo Date: Tue May 13 19:04:07 2008 New Revision: 54710 Modified: pypy/dist/pypy/interpreter/baseobjspace.py pypy/dist/pypy/module/_weakref/interp__weakref.py pypy/dist/pypy/module/_weakref/test/test_weakref.py Log: Give some useful information in the __repr__ of weakrefs, like CPython. Give just as much information in the __repr__ of weakproxies, unlike CPython. Modified: pypy/dist/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/dist/pypy/interpreter/baseobjspace.py (original) +++ pypy/dist/pypy/interpreter/baseobjspace.py Tue May 13 19:04:07 2008 @@ -76,7 +76,7 @@ return default raise - def getrepr(self, space, info): + def getrepr(self, space, info, moreinfo=''): # XXX slowish w_id = space.id(self) w_4 = space.wrap(4) @@ -93,7 +93,8 @@ if i == 0: break w_id = space.rshift(w_id, w_4) - return space.wrap("<%s at 0x%s>" % (info, ''.join(addrstring))) + return space.wrap("<%s at 0x%s%s>" % (info, ''.join(addrstring), + moreinfo)) def getslotvalue(self, index): raise NotImplementedError Modified: pypy/dist/pypy/module/_weakref/interp__weakref.py ============================================================================== --- pypy/dist/pypy/module/_weakref/interp__weakref.py (original) +++ pypy/dist/pypy/module/_weakref/interp__weakref.py Tue May 13 19:04:07 2008 @@ -161,6 +161,21 @@ def descr__ne__(space, ref1, ref2): return space.not_(space.eq(ref1, ref2)) +def descr__repr__(space, ref): + w_obj = ref.dereference() + if w_obj is None: + state = '; dead' + else: + typename = space.type(w_obj).getname(space, '?') + objname = w_obj.getname(space, '') + if objname: + state = "; to '%s' (%s)" % (typename, objname) + else: + state = "; to '%s'" % (typename,) + return ref.getrepr(space, ref.typedef.name, state) + +reprdescr = interp2app(descr__repr__, unwrap_spec=[ObjSpace, W_WeakrefBase]) + W_Weakref.typedef = TypeDef("weakref", __doc__ = """A weak reference to an object 'obj'. A 'callback' can given, which is called with the weak reference as an argument when 'obj' @@ -171,6 +186,7 @@ __ne__ = interp2app(descr__ne__, unwrap_spec=[ObjSpace, W_Weakref, W_Weakref]), __hash__ = interp2app(W_Weakref.descr_hash, unwrap_spec=['self']), + __repr__ = reprdescr, __call__ = interp2app(W_Weakref.descr_call, unwrap_spec=['self']) ) @@ -267,12 +283,14 @@ W_Proxy.typedef = TypeDef("weakproxy", __new__ = interp2app(descr__new__proxy), __hash__ = interp2app(W_Proxy.descr__hash__, unwrap_spec=['self', ObjSpace]), + __repr__ = reprdescr, **proxy_typedef_dict) W_Proxy.typedef.acceptable_as_base_class = False W_CallableProxy.typedef = TypeDef("weakcallableproxy", __new__ = interp2app(descr__new__callableproxy), __hash__ = interp2app(W_Proxy.descr__hash__, unwrap_spec=['self', ObjSpace]), + __repr__ = reprdescr, __call__ = interp2app(W_CallableProxy.descr__call__, unwrap_spec=['self', ObjSpace, Arguments]), **callable_proxy_typedef_dict) Modified: pypy/dist/pypy/module/_weakref/test/test_weakref.py ============================================================================== --- pypy/dist/pypy/module/_weakref/test/test_weakref.py (original) +++ pypy/dist/pypy/module/_weakref/test/test_weakref.py Tue May 13 19:04:07 2008 @@ -359,3 +359,28 @@ pass return A raises(TypeError, tryit) + + def test_repr(self): + import _weakref, gc + for kind in ('ref', 'proxy'): + def foobaz(): pass + w = getattr(_weakref, kind)(foobaz) + s = repr(w) + print s + if kind == 'ref': + assert s.startswith(' Author: docgok Date: Wed May 14 00:40:47 2008 New Revision: 54717 Modified: pypy/branch/hybrid-io/pypy/translator/c/test/test_newgc.py Log: New string building test for the new GC Modified: pypy/branch/hybrid-io/pypy/translator/c/test/test_newgc.py ============================================================================== --- pypy/branch/hybrid-io/pypy/translator/c/test/test_newgc.py (original) +++ pypy/branch/hybrid-io/pypy/translator/c/test/test_newgc.py Wed May 14 00:40:47 2008 @@ -12,6 +12,7 @@ from pypy.rpython.lltypesystem.lloperation import llop from pypy.rpython.memory.test import snippet from pypy.rlib.objectmodel import keepalive_until_here +from pypy.rlib.rstring import StringBuilder, UnicodeBuilder from pypy import conftest from pypy.tool.udir import udir @@ -983,6 +984,30 @@ c_fn = self.getcompiled(fn) res = c_fn() assert res == 2 + + def test_string_builder(self): + def fn(): + s = StringBuilder() + s.append("a") + s.append("abc") + s.append_slice("abc", 1, 2) + s.append_multiple_char('d', 4) + return s.build() + c_fn = self.getcompiled(fn) + res = c_fn() + assert res == "aabcbdddd" + + def test_string_builder_over_allocation(self): + def fn(): + s = StringBuilder(1024) + s.append("abcd") + s.append("defg") + s.append("rty") + s.append_multiple_char('y', 1000) + return s.build() + c_fn = self.getcompiled(fn) + res = c_fn() + assert res[1000] == 'y' class TestGenerationalGC(TestSemiSpaceGC): gcpolicy = "generation" From fijal at codespeak.net Wed May 14 00:49:29 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 14 May 2008 00:49:29 +0200 (CEST) Subject: [pypy-svn] r54718 - pypy/branch/hybrid-io/pypy/translator/c/test Message-ID: <20080513224929.DCBF6169EF0@codespeak.net> Author: fijal Date: Wed May 14 00:49:28 2008 New Revision: 54718 Modified: pypy/branch/hybrid-io/pypy/translator/c/test/test_newgc.py Log: Add a segfaulting test Modified: pypy/branch/hybrid-io/pypy/translator/c/test/test_newgc.py ============================================================================== --- pypy/branch/hybrid-io/pypy/translator/c/test/test_newgc.py (original) +++ pypy/branch/hybrid-io/pypy/translator/c/test/test_newgc.py Wed May 14 00:49:28 2008 @@ -998,12 +998,15 @@ assert res == "aabcbdddd" def test_string_builder_over_allocation(self): + import gc def fn(): - s = StringBuilder(1024) + s = StringBuilder(4) s.append("abcd") s.append("defg") s.append("rty") s.append_multiple_char('y', 1000) + gc.collect() + s.append_multiple_char('y', 1000) return s.build() c_fn = self.getcompiled(fn) res = c_fn() @@ -1018,5 +1021,8 @@ should_be_moving = True GC_CANNOT_MALLOC_NONMOVABLE = False + def test_string_builder_over_allocation(self): + py.test.skip("Segfaulting") + def test_gc_set_max_heap_size(self): py.test.skip("not implemented") From fijal at codespeak.net Wed May 14 00:54:24 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 14 May 2008 00:54:24 +0200 (CEST) Subject: [pypy-svn] r54719 - pypy/branch/hybrid-io/pypy/rpython/memory/test Message-ID: <20080513225424.856C8169EF0@codespeak.net> Author: fijal Date: Wed May 14 00:54:23 2008 New Revision: 54719 Modified: pypy/branch/hybrid-io/pypy/rpython/memory/test/test_transformed_gc.py Log: Add a problematic test that seems to fail a bit too often. Modified: pypy/branch/hybrid-io/pypy/rpython/memory/test/test_transformed_gc.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/memory/test/test_transformed_gc.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/memory/test/test_transformed_gc.py Wed May 14 00:54:23 2008 @@ -10,6 +10,7 @@ from pypy.rlib.objectmodel import compute_unique_id from pypy.rlib.debug import ll_assert from pypy import conftest +from pypy.rlib.rstring import StringBuilder INT_SIZE = struct.calcsize("i") # only for estimates @@ -507,6 +508,22 @@ run = self.runner(f) assert run([]) == 1 + def test_string_builder_over_allocation(self): + import gc + py.test.skip("Problematic test") + def fn(): + s = StringBuilder(4) + s.append("abcd") + s.append("defg") + s.append("rty") + s.append_multiple_char('y', 1000) + gc.collect() + s.append_multiple_char('y', 1000) + return s.build()[1000] + fn = self.runner(fn) + res = fn([]) + assert res == 'y' + class GenericMovingGCTests(GenericGCTests): GC_CAN_MOVE = True GC_CANNOT_MALLOC_NONMOVABLE = True From afa at codespeak.net Wed May 14 10:26:56 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Wed, 14 May 2008 10:26:56 +0200 (CEST) Subject: [pypy-svn] r54720 - in pypy/dist/pypy/rpython/lltypesystem: . test Message-ID: <20080514082656.E4AAA16851E@codespeak.net> Author: afa Date: Wed May 14 10:26:55 2008 New Revision: 54720 Modified: pypy/dist/pypy/rpython/lltypesystem/rffi.py pypy/dist/pypy/rpython/lltypesystem/test/test_rffi.py Log: Correct the translation of rffi.make, when no fields are initialized: exception_is_here should point to an actual llop... Found in the win32 version of rpoll.poll(). Could not simplify the test more, though. Modified: pypy/dist/pypy/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rffi.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rffi.py Wed May 14 10:26:55 2008 @@ -597,9 +597,9 @@ vlist = [hop.inputarg(lltype.Void, arg=0)] flags = {'flavor':'raw'} vlist.append(hop.inputconst(lltype.Void, flags)) - v_ptr = hop.genop('malloc', vlist, resulttype=hop.r_result.lowleveltype) hop.has_implicit_exception(MemoryError) # record that we know about it hop.exception_is_here() + v_ptr = hop.genop('malloc', vlist, resulttype=hop.r_result.lowleveltype) for name, i in fields.items(): name = name[2:] v_arg = hop.inputarg(hop.args_r[i], arg=i) Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_rffi.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/test/test_rffi.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/test/test_rffi.py Wed May 14 10:26:55 2008 @@ -464,6 +464,18 @@ res = interpret(f, []) assert res == 123 + def test_make_annotation(self): + X = CStruct('xx', ('one', INT)) + def f(): + p = make(X) + try: + q = make(X) + lltype.free(q, flavor='raw') + finally: + lltype.free(p, flavor='raw') + return 3 + assert interpret(f, []) == 3 + def test_implicit_cast(self): z = llexternal('z', [USHORT, ULONG, USHORT, DOUBLE], USHORT) From afa at codespeak.net Wed May 14 11:16:49 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Wed, 14 May 2008 11:16:49 +0200 (CEST) Subject: [pypy-svn] r54725 - in pypy/dist/pypy: rpython/lltypesystem rpython/lltypesystem/test translator/c translator/tool Message-ID: <20080514091649.199B11684FA@codespeak.net> Author: afa Date: Wed May 14 11:16:47 2008 New Revision: 54725 Modified: pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py pypy/dist/pypy/rpython/lltypesystem/rffi.py pypy/dist/pypy/rpython/lltypesystem/test/test_ll2ctypes.py pypy/dist/pypy/rpython/lltypesystem/test/test_rffi.py pypy/dist/pypy/translator/c/genc.py pypy/dist/pypy/translator/tool/cbuild.py Log: Make CExtModuleBuilder and ll2ctypes work on win32: - export all needed symbols when building a dll - eventually compile with debug info - load the correct libc, depending on compiler version and options. test_rffi and test_ll2ctypes pass, and probably many others. Modified: pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py Wed May 14 11:16:47 2008 @@ -519,13 +519,27 @@ if ctypes: if sys.platform == 'win32': - # trying to guess the correct libc... only a few tests fail if there - # is a mismatch between the one used by python2x.dll and the one - # loaded here - if sys.version_info < (2, 4): - standard_c_lib = ctypes.cdll.LoadLibrary('msvcrt.dll') + # Parses sys.version and deduces the version of the compiler + import distutils.msvccompiler + version = distutils.msvccompiler.get_build_version() + if version is None: + # This logic works with official builds of Python. + if sys.version_info < (2, 4): + clibname = 'msvcrt' + else: + clibname = 'msvcr71' else: - standard_c_lib = ctypes.cdll.LoadLibrary('msvcr71.dll') + if version <= 6: + clibname = 'msvcrt' + else: + clibname = 'msvcr%d' % (version * 10) + + # If python was built with in debug mode + import imp + if imp.get_suffixes()[0][0] == '_d.pyd': + clibname += 'd' + + standard_c_lib = ctypes.cdll.LoadLibrary(clibname+'.dll') else: standard_c_lib = ctypes.cdll.LoadLibrary(ctypes.util.find_library('c')) Modified: pypy/dist/pypy/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rffi.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rffi.py Wed May 14 11:16:47 2008 @@ -406,6 +406,7 @@ new_eci = eci.merge(ExternalCompilationInfo( separate_module_sources = sources, post_include_lines = [getter_prototype, setter_prototype], + export_symbols = [getter_name, setter_name], )) getter = llexternal(getter_name, [], TYPE, compilation_info=new_eci, Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_ll2ctypes.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/test/test_ll2ctypes.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/test/test_ll2ctypes.py Wed May 14 11:16:47 2008 @@ -267,8 +267,11 @@ assert not ALLOCATED # detects memory leaks in the test def test_frexp(self): - eci = ExternalCompilationInfo(includes=['math.h'], - libraries=['m']) + if sys.platform != 'win32': + eci = ExternalCompilationInfo(includes=['math.h'], + libraries=['m']) + else: + eci = ExternalCompilationInfo(includes=['math.h']) A = lltype.FixedSizeArray(rffi.INT, 1) frexp = rffi.llexternal('frexp', [rffi.DOUBLE, lltype.Ptr(A)], rffi.DOUBLE, compilation_info=eci) @@ -299,6 +302,8 @@ assert not ALLOCATED # detects memory leaks in the test def test_opaque_obj(self): + if sys.platform == 'win32': + py.test.skip("No gettimeofday on win32") eci = ExternalCompilationInfo( includes = ['sys/time.h', 'time.h'] ) @@ -683,6 +688,8 @@ assert abs(float(b[2]) - 2.2) < 1E-6 def test_different_signatures(self): + if sys.platform=='win32': + py.test.skip("No fcntl on win32") fcntl_int = rffi.llexternal('fcntl', [rffi.INT, rffi.INT, rffi.INT], rffi.INT) fcntl_str = rffi.llexternal('fcntl', [rffi.INT, rffi.INT, rffi.CCHARP], @@ -693,7 +700,8 @@ def test_llexternal_source(self): eci = ExternalCompilationInfo( - separate_module_sources = ["int fn() { return 42; }"] + separate_module_sources = ["int fn() { return 42; }"], + export_symbols = ['fn'], ) fn = rffi.llexternal('fn', [], rffi.INT, compilation_info=eci) res = fn() @@ -745,7 +753,8 @@ } """) - eci = ExternalCompilationInfo(separate_module_sources=[c_source]) + eci = ExternalCompilationInfo(separate_module_sources=[c_source], + export_symbols=['eating_callback']) args = [rffi.INT, rffi.CCallback([rffi.INT], rffi.INT)] eating_callback = rffi.llexternal('eating_callback', args, rffi.INT, Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_rffi.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/test/test_rffi.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/test/test_rffi.py Wed May 14 11:16:47 2008 @@ -1,5 +1,6 @@ import py +import sys from pypy.rpython.lltypesystem.rffi import * from pypy.rpython.lltypesystem.rffi import _keeper_for_type # crap from pypy.rlib.rposix import get_errno, set_errno @@ -347,7 +348,8 @@ eci = ExternalCompilationInfo(includes=['callback.h'], include_dirs=[str(udir)], - separate_module_sources=[c_source]) + separate_module_sources=[c_source], + export_symbols=['eating_callback']) args = [INT, CCallback([INT], INT)] eating_callback = llexternal('eating_callback', args, INT, @@ -530,6 +532,8 @@ assert interpret(f, [], backendopt=True) == 43 def test_around_extcall(self): + if sys.platform == "win32": + py.test.skip('No pipes on windows') import os from pypy.annotation import model as annmodel from pypy.rlib.objectmodel import invoke_around_extcall Modified: pypy/dist/pypy/translator/c/genc.py ============================================================================== --- pypy/dist/pypy/translator/c/genc.py (original) +++ pypy/dist/pypy/translator/c/genc.py Wed May 14 11:16:47 2008 @@ -181,7 +181,10 @@ def __del__(self): import sys - from _ctypes import dlclose + if sys.platform == "win32": + from _ctypes import FreeLibrary as dlclose + else: + from _ctypes import dlclose # XXX fish fish fish mod = self.__dict__['mod'] dlclose(mod._lib._handle) @@ -204,9 +207,15 @@ def compile(self): assert self.c_source_filename assert not self._compiled + export_symbols = [self.db.get(self.getentrypointptr()), + 'RPython_StartupCode', + ] + if self.config.translation.countmallocs: + export_symbols.append('malloc_counters') compile_c_module([self.c_source_filename] + self.extrafiles, self.c_source_filename.purebasename, self.eci, - tmpdir=self.c_source_filename.dirpath()) + tmpdir=self.c_source_filename.dirpath(), + export_symbols=export_symbols) self._compiled = True def _make_wrapper_module(self): @@ -219,7 +228,7 @@ CODE = """ import ctypes -_lib = ctypes.PyDLL("%(so_name)s") +_lib = ctypes.PyDLL(r"%(so_name)s") _entry_point = getattr(_lib, "%(c_entrypoint_name)s") _entry_point.restype = ctypes.py_object Modified: pypy/dist/pypy/translator/tool/cbuild.py ============================================================================== --- pypy/dist/pypy/translator/tool/cbuild.py (original) +++ pypy/dist/pypy/translator/tool/cbuild.py Wed May 14 11:16:47 2008 @@ -16,7 +16,8 @@ _ATTRIBUTES = ['pre_include_lines', 'includes', 'include_dirs', 'post_include_lines', 'libraries', 'library_dirs', - 'separate_module_sources', 'separate_module_files'] + 'separate_module_sources', 'separate_module_files', + 'export_symbols'] _AVOID_DUPLICATES = ['separate_module_files', 'libraries', 'includes', 'include_dirs', 'library_dirs', 'separate_module_sources'] @@ -28,7 +29,8 @@ libraries = [], library_dirs = [], separate_module_sources = [], - separate_module_files = []): + separate_module_files = [], + export_symbols = []): """ pre_include_lines: list of lines that should be put at the top of the generated .c files, before any #include. They shouldn't @@ -196,7 +198,8 @@ opt += '/Op' gcv['OPT'] = opt -def compile_c_module(cfiles, modbasename, eci, tmpdir=None): +def compile_c_module(cfiles, modbasename, eci, tmpdir=None, + export_symbols=None): #try: # from distutils.log import set_threshold # set_threshold(10000) @@ -220,6 +223,11 @@ os.path.exists(s + 'lib'): library_dirs.append(s + 'lib') + if export_symbols is None: + export_symbols = list(eci.export_symbols) + else: + export_symbols = list(eci.export_symbols) + export_symbols + num = 0 modname = modbasename while 1: @@ -253,11 +261,17 @@ from distutils.ccompiler import get_default_compiler from distutils.command.build_ext import build_ext - class build_ext_no_additional_symbol(build_ext): + class build_shared_library(build_ext): + """ We build shared libraries, not python modules. + On windows, avoid to export the initXXX function, + and don't use a .pyd extension. """ def get_export_symbols(self, ext): - """ work around a 'feature' of distutils that forces every - module to have a certain symbol on win """ return ext.export_symbols + def get_ext_filename (self, ext_name): + if sys.platform == 'win32': + return ext_name + ".dll" + else: + return ext_name + ".so" saved_environ = os.environ.items() try: @@ -290,7 +304,9 @@ include_dirs=include_dirs, library_dirs=library_dirs, extra_compile_args=extra_compile_args, - libraries=list(libraries),) + libraries=list(libraries), + export_symbols=export_symbols, + ) ], 'script_name': 'setup.py', 'script_args': ['-q', 'build_ext'], # don't remove 'build_ext' here @@ -299,9 +315,11 @@ # patch our own command obj into distutils # because it does not have a facility to accept # custom objects - cmdobj = build_ext_no_additional_symbol(dist) + cmdobj = build_shared_library(dist) cmdobj.inplace = True cmdobj.force = True + if sys.platform == 'win32' and sys.executable.endswith('_d.exe'): + cmdobj.debug = True dist.command_obj["build_ext"] = cmdobj dist.have_run["build_ext"] = 0 From xoraxax at codespeak.net Wed May 14 11:41:10 2008 From: xoraxax at codespeak.net (xoraxax at codespeak.net) Date: Wed, 14 May 2008 11:41:10 +0200 (CEST) Subject: [pypy-svn] r54726 - in pypy/dist/pypy/translator: c tool Message-ID: <20080514094110.25C0A168518@codespeak.net> Author: xoraxax Date: Wed May 14 11:41:08 2008 New Revision: 54726 Modified: pypy/dist/pypy/translator/c/genc.py pypy/dist/pypy/translator/tool/cbuild.py Log: Rectify stylistic sanity and remove the export_symbols param for compile_c_module again, and document the new field in ECI. Modified: pypy/dist/pypy/translator/c/genc.py ============================================================================== --- pypy/dist/pypy/translator/c/genc.py (original) +++ pypy/dist/pypy/translator/c/genc.py Wed May 14 11:41:08 2008 @@ -212,10 +212,11 @@ ] if self.config.translation.countmallocs: export_symbols.append('malloc_counters') + extsymeci = ExternalCompilationInfo(export_symbols=export_symbols) + self.eci = self.eci.merge(extsymeci) compile_c_module([self.c_source_filename] + self.extrafiles, self.c_source_filename.purebasename, self.eci, - tmpdir=self.c_source_filename.dirpath(), - export_symbols=export_symbols) + tmpdir=self.c_source_filename.dirpath()) self._compiled = True def _make_wrapper_module(self): Modified: pypy/dist/pypy/translator/tool/cbuild.py ============================================================================== --- pypy/dist/pypy/translator/tool/cbuild.py (original) +++ pypy/dist/pypy/translator/tool/cbuild.py Wed May 14 11:41:08 2008 @@ -56,6 +56,9 @@ separate_module_files: list of .c file names that are compiled separately and linked later on. (If an .h file is needed for other .c files to access this, it can be put in includes.) + + export_symbols: list of names that should be exported by the final + binary. """ for name in self._ATTRIBUTES: value = locals()[name] @@ -198,8 +201,7 @@ opt += '/Op' gcv['OPT'] = opt -def compile_c_module(cfiles, modbasename, eci, tmpdir=None, - export_symbols=None): +def compile_c_module(cfiles, modbasename, eci, tmpdir=None): #try: # from distutils.log import set_threshold # set_threshold(10000) @@ -223,10 +225,7 @@ os.path.exists(s + 'lib'): library_dirs.append(s + 'lib') - if export_symbols is None: - export_symbols = list(eci.export_symbols) - else: - export_symbols = list(eci.export_symbols) + export_symbols + export_symbols = list(eci.export_symbols) num = 0 modname = modbasename From antocuni at codespeak.net Wed May 14 12:31:28 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 14 May 2008 12:31:28 +0200 (CEST) Subject: [pypy-svn] r54727 - in pypy/branch/oo-jit/pypy/jit/codegen: cli cli/test test Message-ID: <20080514103128.B596B168526@codespeak.net> Author: antocuni Date: Wed May 14 12:31:27 2008 New Revision: 54727 Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/dumpgenerator.py pypy/branch/oo-jit/pypy/jit/codegen/cli/operation.py pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_interpreter.py pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_rgenop.py pypy/branch/oo-jit/pypy/jit/codegen/test/rgenop_tests.py Log: a big refactoring to cli jit backend; the main Builder is now a GraphBuilder, which is only a collections of one or more BranchBuilder; instead of generating code, BranchBuilders store operations in a list, which are then serialized to CLI bytecode only at the end. This solves a couple of problems and make some more tests passing Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/dumpgenerator.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/codegen/cli/dumpgenerator.py (original) +++ pypy/branch/oo-jit/pypy/jit/codegen/cli/dumpgenerator.py Wed May 14 12:31:27 2008 @@ -8,7 +8,7 @@ def _fmt(self, arg): from System.Reflection import Emit, FieldInfo if isinstance(arg, Emit.LocalBuilder): - return 'v%d' % arg.LocalIndex + return 'var%d' % arg.LocalIndex elif isinstance(arg, Emit.Label): return 'label%d' % self.labels[arg] elif isinstance(arg, FieldInfo): Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/operation.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/codegen/cli/operation.py (original) +++ pypy/branch/oo-jit/pypy/jit/codegen/cli/operation.py Wed May 14 12:31:27 2008 @@ -17,7 +17,7 @@ if self._gv_res is None: restype = self.restype() if restype is not None: - loc = self.builder.il.DeclareLocal(restype) + loc = self.builder.parent.il.DeclareLocal(restype) self._gv_res = GenLocalVar(loc) return self._gv_res @@ -41,7 +41,7 @@ def emit(self): self.pushAllArgs() - self.builder.il.Emit(self.getOpCode()) + self.builder.parent.il.Emit(self.getOpCode()) self.storeResult() def getOpCode(self): @@ -59,7 +59,7 @@ def emit(self): self.pushAllArgs() - self.builder.il.Emit(self.getOpCode()) + self.builder.parent.il.Emit(self.getOpCode()) self.storeResult() def getOpCode(self): @@ -82,8 +82,8 @@ return None def emit(self): - self.builder.il.MarkLabel(self.label) - + self.builder.parent.il.MarkLabel(self.label) + class FollowLink(Operation): def __init__(self, builder, outputargs_gv, inputargs_gv, label): @@ -99,7 +99,8 @@ for i in range(len(self.outputargs_gv)): self.outputargs_gv[i].load(self.builder) self.inputargs_gv[i].store(self.builder) - self.builder.il.Emit(OpCodes.Br, self.label) + self.builder.parent.il.Emit(OpCodes.Br, self.label) + class Branch(Operation): @@ -115,7 +116,7 @@ def emit(self): if self.gv_cond is not None: self.gv_cond.load(self.builder) - self.builder.il.Emit(self.opcode, self.label) + self.builder.parent.il.Emit(self.opcode, self.label) class Return(Operation): @@ -127,9 +128,12 @@ return None def emit(self): + retvar = self.builder.parent.retvar + retlabel = self.builder.parent.retlabel if self.gv_x is not None: self.gv_x.load(self.builder) - self.builder.il.Emit(OpCodes.Ret) + self.builder.parent.il.Emit(OpCodes.Stloc, retvar) + self.builder.parent.il.Emit(OpCodes.Br, retlabel) class Call(Operation): @@ -149,10 +153,10 @@ delegate_type = class2type(self.sigtoken.funcclass) meth_invoke = delegate_type.GetMethod('Invoke') self.gv_fnptr.load(self.builder) - self.builder.il.Emit(OpCodes.Castclass, delegate_type) + self.builder.parent.il.Emit(OpCodes.Castclass, delegate_type) for gv_arg in self.args_gv: gv_arg.load(self.builder) - self.builder.il.EmitCall(OpCodes.Callvirt, meth_invoke, None) + self.builder.parent.il.EmitCall(OpCodes.Callvirt, meth_invoke, None) self.storeResult() @@ -226,7 +230,7 @@ if 'call' in step: return # XXX, fix this attrname = opcode2attrname(step) - body.append('self.builder.il.Emit(OpCodes.%s)' % attrname) + body.append('self.builder.parent.il.Emit(OpCodes.%s)' % attrname) elif isinstance(step, cli_opcodes.MapException): return # XXX, TODO else: Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py (original) +++ pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py Wed May 14 12:31:27 2008 @@ -12,7 +12,6 @@ OpCodes = System.Reflection.Emit.OpCodes DUMP_IL = False -DEBUG = False cVoid = ootype.nullruntimeclass cInt32 = classof(System.Int32) @@ -57,18 +56,18 @@ def load(self, builder): if self.index == 0: - builder.il.Emit(OpCodes.Ldarg_0) + builder.parent.il.Emit(OpCodes.Ldarg_0) elif self.index == 1: - builder.il.Emit(OpCodes.Ldarg_1) + builder.parent.il.Emit(OpCodes.Ldarg_1) elif self.index == 2: - builder.il.Emit(OpCodes.Ldarg_2) + builder.parent.il.Emit(OpCodes.Ldarg_2) elif self.index == 3: - builder.il.Emit(OpCodes.Ldarg_3) + builder.parent.il.Emit(OpCodes.Ldarg_3) else: - builder.il.Emit(OpCodes.Ldarg, self.index) + builder.parent.il.Emit(OpCodes.Ldarg, self.index) def store(self, builder): - builder.il.Emit(OpCodes.Starg, self.index) + builder.parent.il.Emit(OpCodes.Starg, self.index) def __repr__(self): return "GenArgVar(%d)" % self.index @@ -81,10 +80,10 @@ return self.v.get_LocalType() def load(self, builder): - builder.il.Emit(OpCodes.Ldloc, self.v) + builder.parent.il.Emit(OpCodes.Ldloc, self.v) def store(self, builder): - builder.il.Emit(OpCodes.Stloc, self.v) + builder.parent.il.Emit(OpCodes.Stloc, self.v) class IntConst(GenConst): @@ -108,7 +107,7 @@ return class2type(self.cliclass) def load(self, builder): - builder.il.Emit(OpCodes.Ldc_I4, self.value) + builder.parent.il.Emit(OpCodes.Ldc_I4, self.value) def __repr__(self): return "int const=%s" % self.value @@ -128,7 +127,7 @@ return typeof(System.Double) def load(self, builder): - builder.il.Emit(OpCodes.Ldc_R8, self.value) + builder.parent.il.Emit(OpCodes.Ldc_R8, self.value) def __repr__(self): return "float const=%s" % self.value @@ -145,10 +144,10 @@ return index def _load_from_array(self, builder, index, clitype): - builder.il.Emit(OpCodes.Ldarg_0) - builder.il.Emit(OpCodes.Ldc_I4, index) - builder.il.Emit(OpCodes.Ldelem_Ref) - builder.il.Emit(OpCodes.Castclass, clitype) + builder.parent.il.Emit(OpCodes.Ldarg_0) + builder.parent.il.Emit(OpCodes.Ldc_I4, index) + builder.parent.il.Emit(OpCodes.Ldelem_Ref) + builder.parent.il.Emit(OpCodes.Castclass, clitype) def getobj(self): raise NotImplementedError @@ -162,6 +161,7 @@ return self.obj def load(self, builder): + import pdb;pdb.set_trace() index = self._get_index(builder) if self.obj is None: t = typeof(System.Object) @@ -171,6 +171,10 @@ @specialize.arg(1) def revealconst(self, T): + if T is ootype.Signed: + return 12345 + elif T is ootype.Unsigned: + return 12346 return ootype.cast_from_object(T, self.obj) @@ -192,8 +196,8 @@ delegatetype = self.delegatetype index = self._get_index(builder) self._load_from_array(builder, index, holdertype) - builder.il.Emit(OpCodes.Ldfld, funcfield) - builder.il.Emit(OpCodes.Castclass, delegatetype) + builder.parent.il.Emit(OpCodes.Ldfld, funcfield) + builder.parent.il.Emit(OpCodes.Castclass, delegatetype) @specialize.arg(1) def revealconst(self, T): @@ -282,11 +286,11 @@ for i in range(len(argsclass)): args[i+1] = class2type(argsclass[i]) res = class2type(sigtoken.res) - builder = Builder(self, name, res, args, sigtoken) + builder = GraphBuilder(self, name, res, args, sigtoken) return builder, builder.gv_entrypoint, builder.inputargs_gv[:] -class Builder(GenBuilder): +class GraphBuilder(GenBuilder): def __init__(self, rgenop, name, res, args, sigtoken): self.rgenop = rgenop @@ -300,123 +304,148 @@ self.inputargs_gv.append(GenArgVar(i, args[i])) self.delegatetype = class2type(sigtoken.funcclass) self.gv_entrypoint = FunctionConst(self.delegatetype) - self.isOpen = False - self.operations = [] - self.branches = [] - self.returnblocks = [] self.genconsts = {} + self.branches = [BranchBuilder(self, self.il.DefineLabel())] + restype = class2type(sigtoken.res) + if restype is not None: + self.retvar = self.il.DeclareLocal(restype) + else: + self.retvar = None + self.retlabel = self.il.DefineLabel() + + def appendbranch(self, branchbuilder): + self.branches.append(branchbuilder) + + def start_writing(self): + self.branches[0].start_writing() + + def pause_writing(self, args_gv): + return self.branches[0].pause_writing(args_gv) + + def finish_and_return(self, sigtoken, gv_returnvar): + return self.branches[0].finish_and_return(sigtoken, + gv_returnvar) + + def finish_and_goto(self, outputargs_gv, target): + return self.branches[0].finish_and_goto(outputargs_gv, target) + + def enter_next_block(self, args_gv): + return self.branches[0].enter_next_block(args_gv) + + def jump_if_false(self, gv_condition, args_for_jump_gv): + return self.branches[0].jump_if_false(gv_condition, + args_for_jump_gv) + + def jump_if_true(self, gv_condition, args_for_jump_gv): + return self.branches[0].jump_if_true(gv_condition, + args_for_jump_gv) @specialize.arg(1) def genop1(self, opname, gv_arg): - opcls = ops.getopclass1(opname) - op = opcls(self, gv_arg) - self.emit(op) - gv_res = op.gv_res() - if DEBUG: - self.il.EmitWriteLine(opname) - self.writeline_gv(gv_arg) - self.writeline_gv(gv_res) - self.il.EmitWriteLine('') - return gv_res + return self.branches[0].genop1(opname, gv_arg) @specialize.arg(1) def genop2(self, opname, gv_arg1, gv_arg2): - opcls = ops.getopclass2(opname) - op = opcls(self, gv_arg1, gv_arg2) - self.emit(op) - gv_res = op.gv_res() - if DEBUG: - self.il.EmitWriteLine(opname) - self.writeline_gv(gv_arg1) - self.writeline_gv(gv_arg2) - self.writeline_gv(gv_res) - self.il.EmitWriteLine('') - return gv_res - - def writeline_gv(self, gv): - if isinstance(gv, GenLocalVar): - self.il.EmitWriteLine(gv.v) - elif isinstance(gv, IntConst): - self.il.EmitWriteLine('%s' % gv.value) - else: - assert False + return self.branches[0].genop2(opname, gv_arg1, gv_arg2) def genop_call(self, sigtoken, gv_fnptr, args_gv): - op = ops.Call(self, sigtoken, gv_fnptr, args_gv) - self.emit(op) - return op.gv_res() + return self.branches[0].genop_call(sigtoken, gv_fnptr, args_gv) def genop_same_as(self, gv_x): - op = ops.SameAs(self, gv_x) - self.emit(op) - return op.gv_res() + return self.branches[0].genop_same_as(gv_x) - def genop_getfield(self, fieldtoken, gv_ptr): - pass + def end(self): + # render all the pending branches + for branchbuilder in self.branches: + branchbuilder.replayops() - def genop_setfield(self, fieldtoken, gv_ptr, gv_value): - pass + # render the return block for last, else the verifier could complain + self.il.MarkLabel(self.retlabel) + if self.retvar: + self.il.Emit(OpCodes.Ldloc, self.retvar) + self.il.Emit(OpCodes.Ret) + + # initialize the array of genconsts + consts = new_array(System.Object, len(self.genconsts)) + for gv_const, i in self.genconsts.iteritems(): + consts[i] = gv_const.getobj() + # build the delegate + myfunc = self.meth.CreateDelegate(self.delegatetype, consts) + self.gv_entrypoint.holder.SetFunc(myfunc) - def emit(self, op): - op.emit() - def appendbranch(self, branch): - self.branches.append(branch) +class BranchBuilder(GenBuilder): - def appendreturn(self, retlabel, gv_returnvar): - self.returnblocks.append((retlabel, gv_returnvar)) + def __init__(self, parent, label): + self.parent = parent + self.label = label + self.operations = [] + self.is_open = False + self.genconsts = parent.genconsts def start_writing(self): - self.isOpen = True + self.is_open = True def finish_and_return(self, sigtoken, gv_returnvar): - retlabel = self.il.DefineLabel() - op = ops.Branch(self, None, OpCodes.Br, retlabel) - self.emit(op) - self.appendreturn(retlabel, gv_returnvar) - self.isOpen = False + op = ops.Return(self, gv_returnvar) + self.appendop(op) + self.is_open = False def finish_and_goto(self, outputargs_gv, target): inputargs_gv = target.inputargs_gv assert len(inputargs_gv) == len(outputargs_gv) - op = ops.FollowLink(self, outputargs_gv, inputargs_gv, target.label) - self.emit(op) - self.isOpen = False + op = ops.FollowLink(self, outputargs_gv, inputargs_gv, + target.label) + self.appendop(op) + self.is_open = False - def end(self): - # render all the pending branches - for branch in self.branches: - branch.replayops() + @specialize.arg(1) + def genop1(self, opname, gv_arg): + opcls = ops.getopclass1(opname) + op = opcls(self, gv_arg) + self.appendop(op) + gv_res = op.gv_res() + return gv_res + + @specialize.arg(1) + def genop2(self, opname, gv_arg1, gv_arg2): + opcls = ops.getopclass2(opname) + op = opcls(self, gv_arg1, gv_arg2) + self.appendop(op) + gv_res = op.gv_res() + return gv_res - # render the return blocks for last, else the verifier could complain - for retlabel, gv_returnvar in self.returnblocks: - self.il.MarkLabel(retlabel) - op = ops.Return(self, gv_returnvar) - self.emit(op) + def genop_call(self, sigtoken, gv_fnptr, args_gv): + op = ops.Call(self, sigtoken, gv_fnptr, args_gv) + self.appendop(op) + return op.gv_res() - # initialize the array of genconsts - consts = new_array(System.Object, len(self.genconsts)) - for gv_const, i in self.genconsts.iteritems(): - consts[i] = gv_const.getobj() - # build the delegate - myfunc = self.meth.CreateDelegate(self.delegatetype, consts) - self.gv_entrypoint.holder.SetFunc(myfunc) + def genop_same_as(self, gv_x): + op = ops.SameAs(self, gv_x) + self.appendop(op) + return op.gv_res() + +## def genop_getfield(self, fieldtoken, gv_ptr): +## pass + +## def genop_setfield(self, fieldtoken, gv_ptr, gv_value): +## pass def enter_next_block(self, args_gv): for i in range(len(args_gv)): op = ops.SameAs(self, args_gv[i]) - op.emit() + self.appendop(op) args_gv[i] = op.gv_res() - label = self.il.DefineLabel() - self.emit(ops.MarkLabel(self, label)) + label = self.parent.il.DefineLabel() + self.appendop(ops.MarkLabel(self, label)) return Label(label, args_gv) def _jump_if(self, gv_condition, opcode): - label = self.il.DefineLabel() + label = self.parent.il.DefineLabel() op = ops.Branch(self, gv_condition, opcode, label) - self.emit(op) - branch = BranchBuilder(self, label) - self.appendbranch(branch) + self.appendop(op) + branch = BranchBuilder(self.parent, label) + self.parent.appendbranch(branch) return branch def jump_if_false(self, gv_condition, args_for_jump_gv): @@ -425,43 +454,16 @@ def jump_if_true(self, gv_condition, args_for_jump_gv): return self._jump_if(gv_condition, OpCodes.Brtrue) -class BranchBuilder(Builder): - - def __init__(self, parent, label): - self.parent = parent - self.label = label - self.il = parent.il - self.operations = [] - self.isOpen = False - self.genconsts = parent.genconsts - - def start_writing(self): - self.isOpen = True - - @specialize.arg(1) - def genop2(self, opname, gv_arg1, gv_arg2): - # XXX: this only serves to mask a bug in gencli which I don't - # feel like fixing now. Try to uncomment this and run - # test_goto_compile to see why it fails - return Builder.genop2(self, opname, gv_arg1, gv_arg2) - - def emit(self, op): + def appendop(self, op): self.operations.append(op) - def appendbranch(self, branch): - self.parent.appendbranch(branch) - - def appendreturn(self, retlabel, gv_returnvar): - self.parent.appendreturn(retlabel, gv_returnvar) - def end(self): self.parent.end() def replayops(self): - assert not self.isOpen - assert not self.parent.isOpen + assert not self.is_open il = self.parent.il - il.MarkLabel(self.label) + il.MarkLabel(self.label) for op in self.operations: op.emit() Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_interpreter.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_interpreter.py (original) +++ pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_interpreter.py Wed May 14 12:31:27 2008 @@ -1,9 +1,11 @@ import py from pypy.jit.codegen.cli.rgenop import RCliGenOp +from pypy.jit.codegen.dump.rgenop import RDumpGenOp from pypy.jit.rainbow.test.test_interpreter import TestOOType as RainbowTest class TestRainbowCli(RainbowTest): RGenOp = RCliGenOp + RGenOp = RDumpGenOp # for the individual tests see # ====> ../../../rainbow/test/test_interpreter.py @@ -23,7 +25,7 @@ test_simple_opt_const_propagation1 = skip test_simple_opt_const_propagation2 = skip - test_red_switch = skip + #test_red_switch = skip test_merge = skip test_loop_merging = skip test_loop_merging2 = skip Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_rgenop.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_rgenop.py (original) +++ pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_rgenop.py Wed May 14 12:31:27 2008 @@ -70,11 +70,8 @@ py.test.skip('fixme: add support for frames') def test_from_random_direct(self): - py.test.skip('mono crashes') - - def test_from_random_3_direct(self): - py.test.skip('infinite loop') - + py.test.skip('mono crash') + def test_from_random_5_direct(self): py.test.skip('mono crash') Modified: pypy/branch/oo-jit/pypy/jit/codegen/test/rgenop_tests.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/codegen/test/rgenop_tests.py (original) +++ pypy/branch/oo-jit/pypy/jit/codegen/test/rgenop_tests.py Wed May 14 12:31:27 2008 @@ -2670,3 +2670,34 @@ fnptr = self.cast(gv_fn, 0, RESULT=lltype.Void) #res = fnptr() -- xxx fix me, cannot be run so far + + def test_red_switch(self): + """ + This code is derived from the one produced by the dump backend + when running rainbow.test_interpreter.test_red_switch. + """ + rgenop = self.RGenOp() + sigtoken = rgenop.sigToken(self.T.FUNC2) + + builder0, gv_callable, [arg1, arg2] = rgenop.newgraph(sigtoken, + 'generated') + builder0.start_writing() + var0 = builder0.genop1('int_is_true', arg1) + builder1 = builder0.jump_if_false(var0, [arg1, arg2, var0]) + builder1.start_writing() + args_gv = [arg2] + label0 = builder1.enter_next_block(args_gv) + [v3] = args_gv + builder0.start_writing() + builder0.finish_and_goto([arg1], label0) + builder1.start_writing() + args_gv = [v3] + label1 = builder1.enter_next_block(args_gv) + [v4] = args_gv + builder1.finish_and_return(sigtoken, v4) + builder0.end() + + fnptr = self.cast(gv_callable, 2) + result = fnptr(1, 2) + assert result == 1 + From xoraxax at codespeak.net Wed May 14 13:02:03 2008 From: xoraxax at codespeak.net (xoraxax at codespeak.net) Date: Wed, 14 May 2008 13:02:03 +0200 (CEST) Subject: [pypy-svn] r54728 - in pypy/dist/pypy/objspace: std/test test Message-ID: <20080514110203.73C5816854C@codespeak.net> Author: xoraxax Date: Wed May 14 13:01:58 2008 New Revision: 54728 Modified: pypy/dist/pypy/objspace/std/test/test_intobject.py pypy/dist/pypy/objspace/test/test_descroperation.py Log: Added two failing skipped tests that show bugs found by parrotbench. Modified: pypy/dist/pypy/objspace/std/test/test_intobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/test/test_intobject.py (original) +++ pypy/dist/pypy/objspace/std/test/test_intobject.py Wed May 14 13:01:58 2008 @@ -414,6 +414,12 @@ def test_getnewargs(self): assert 0 .__getnewargs__() == (0,) + def test_cmp(self): + skip("Fails with an AttributeError, works in cpython") + assert 1 .__cmp__ + assert int .__cmp__ + + class AppTestIntOptimizedAdd(AppTestInt): def setup_class(cls): from pypy.conftest import gettestobjspace Modified: pypy/dist/pypy/objspace/test/test_descroperation.py ============================================================================== --- pypy/dist/pypy/objspace/test/test_descroperation.py (original) +++ pypy/dist/pypy/objspace/test/test_descroperation.py Wed May 14 13:01:58 2008 @@ -318,6 +318,13 @@ a4 = A() assert (a1 < a3) == (a1 < a4) == (a2 < a3) == (a2 < a4) + def test_setattrweakref(self): + skip("fails, works in cpython") + class P(object): + pass + + setattr(P, "__weakref__", 0) + class AppTestWithBuiltinShortcut(AppTest_Descroperation): OPTIONS = {'objspace.std.builtinshortcut': True} From arigo at codespeak.net Wed May 14 14:03:27 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 14 May 2008 14:03:27 +0200 (CEST) Subject: [pypy-svn] r54729 - in pypy/dist/pypy/objspace: std/test test Message-ID: <20080514120327.30F00168548@codespeak.net> Author: arigo Date: Wed May 14 14:03:25 2008 New Revision: 54729 Modified: pypy/dist/pypy/objspace/std/test/test_intobject.py pypy/dist/pypy/objspace/test/test_descroperation.py Log: Document why these are obscure cases. Modified: pypy/dist/pypy/objspace/std/test/test_intobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/test/test_intobject.py (original) +++ pypy/dist/pypy/objspace/std/test/test_intobject.py Wed May 14 14:03:25 2008 @@ -415,7 +415,10 @@ assert 0 .__getnewargs__() == (0,) def test_cmp(self): - skip("Fails with an AttributeError, works in cpython") + skip("This is a 'wont fix' case") + # We don't have __cmp__, we consistently have __eq__ & the others + # instead. In CPython some types have __cmp__ and some types have + # __eq__ & the others. assert 1 .__cmp__ assert int .__cmp__ Modified: pypy/dist/pypy/objspace/test/test_descroperation.py ============================================================================== --- pypy/dist/pypy/objspace/test/test_descroperation.py (original) +++ pypy/dist/pypy/objspace/test/test_descroperation.py Wed May 14 14:03:25 2008 @@ -320,6 +320,9 @@ def test_setattrweakref(self): skip("fails, works in cpython") + # The issue is that in CPython, none of the built-in types have + # a __weakref__ descriptor, even if their instances are weakrefable. + # Should we emulate this? class P(object): pass From antocuni at codespeak.net Wed May 14 14:42:15 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 14 May 2008 14:42:15 +0200 (CEST) Subject: [pypy-svn] r54730 - pypy/branch/oo-jit/pypy/jit/codegen/i386 Message-ID: <20080514124215.69F7E2A805F@codespeak.net> Author: antocuni Date: Wed May 14 14:42:12 2008 New Revision: 54730 Modified: pypy/branch/oo-jit/pypy/jit/codegen/i386/codebuf_nt.py Log: (fijal) port from ctypes_platform to rffi_platform Modified: pypy/branch/oo-jit/pypy/jit/codegen/i386/codebuf_nt.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/codegen/i386/codebuf_nt.py (original) +++ pypy/branch/oo-jit/pypy/jit/codegen/i386/codebuf_nt.py Wed May 14 14:42:12 2008 @@ -1,11 +1,7 @@ import ctypes -import pypy.rpython.rctypes.implementation -from pypy.rpython.rctypes.tool import ctypes_platform -from pypy.rpython.rctypes.tool.ctypes_platform import ConstantInteger -from pypy.rpython.rctypes.tool.ctypes_platform import SimpleType - - -raise NotImplementedError("this needs to be ported from rctypes to rffi") +from pypy.rpython.tool import rffi_platform +from pypy.rpython.tool.rffi_platform import ConstantInteger +from pypy.rpython.tool.rffi_platform import SimpleType class CConfig: @@ -19,7 +15,7 @@ MEM_RELEASE = ConstantInteger('MEM_RELEASE') PAGE_EXECUTE_READWRITE = ConstantInteger('PAGE_EXECUTE_READWRITE') -globals().update(ctypes_platform.configure(CConfig)) +globals().update(rffi_platform.configure(CConfig)) # cannot use c_void_p as return value of functions :-( PTR = ctypes.POINTER(ctypes.c_char) From fijal at codespeak.net Wed May 14 15:09:41 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 14 May 2008 15:09:41 +0200 (CEST) Subject: [pypy-svn] r54732 - pypy/dist/pypy/jit/codegen/i386 Message-ID: <20080514130941.C25562A8078@codespeak.net> Author: fijal Date: Wed May 14 15:09:41 2008 New Revision: 54732 Modified: pypy/dist/pypy/jit/codegen/i386/codebuf_nt.py Log: partial rewrite to rffi, someone with windows needs to sit on it Modified: pypy/dist/pypy/jit/codegen/i386/codebuf_nt.py ============================================================================== --- pypy/dist/pypy/jit/codegen/i386/codebuf_nt.py (original) +++ pypy/dist/pypy/jit/codegen/i386/codebuf_nt.py Wed May 14 15:09:41 2008 @@ -1,19 +1,19 @@ -import ctypes -import pypy.rpython.rctypes.implementation -from pypy.rpython.rctypes.tool import ctypes_platform -from pypy.rpython.rctypes.tool.ctypes_platform import ConstantInteger -from pypy.rpython.rctypes.tool.ctypes_platform import SimpleType - - -raise NotImplementedError("this needs to be ported from rctypes to rffi") +from pypy.rpython.tool import rffi_pltform +from pypy.rpython.tool.rffi_platform import ConstantInteger +from pypy.rpython.tool.rffi_platform import SimpleType +from pypy.translator.tool.cbuild import ExternalCompilationInfo +from pypy.rpython.lltypesystem import rffi +raise ImportError class CConfig: - _header_ = '#include ' - - SIZE_T = SimpleType('SIZE_T', ctypes.c_long) - DWORD = SimpleType('DWORD', ctypes.c_long) - BOOL = SimpleType('BOOL', ctypes.c_int) + _compilation_info_ = ExternalCompilationInfo( + includes = "windows.h" + ) + + SIZE_T = SimpleType('SIZE_T', rffi.LONG) + DWORD = SimpleType('DWORD', rffi.LONG) + BOOL = SimpleType('BOOL', rffi.INT) MEM_COMMIT = ConstantInteger('MEM_COMMIT') MEM_RESERVE = ConstantInteger('MEM_RESERVE') MEM_RELEASE = ConstantInteger('MEM_RELEASE') @@ -22,27 +22,30 @@ globals().update(ctypes_platform.configure(CConfig)) # cannot use c_void_p as return value of functions :-( -PTR = ctypes.POINTER(ctypes.c_char) +# XXX how to get kernel32? VirtualAlloc = ctypes.windll.kernel32.VirtualAlloc -VirtualAlloc.argtypes = [PTR, SIZE_T, DWORD, DWORD] -VirtualAlloc.restype = PTR +VirtualAlloc.argtypes = [rffi.VOIDP, rffi.SIZE_T, DWORD, DWORD] +VirtualAlloc.restype = rffi.VOIDP +DWORD_P = rffi.CArrayPtr(DWORD) VirtualProtect = ctypes.windll.kernel32.VirtualProtect -VirtualProtect.argtypes = [PTR, SIZE_T, DWORD, ctypes.POINTER(DWORD)] +VirtualProtect.argtypes = [rffi.VOIDP, rffi.SIZE_T, DWORD, DWORD_P] VirtualProtect.restype = BOOL VirtualFree = ctypes.windll.kernel32.VirtualFree -VirtualFree.argtypes = [PTR, SIZE_T, DWORD] +VirtualFree.argtypes = [rffi.VOIDP, rffi.SIZE_T, DWORD] VirtualFree.restype = BOOL # ____________________________________________________________ def alloc(map_size): - res = VirtualAlloc(PTR(), map_size, MEM_COMMIT|MEM_RESERVE, + null = lltype.nullptr(rffi.VOIDP) + res = VirtualAlloc(null, map_size, MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE) if not res: raise MemoryError + XXX # rewrite old = DWORD() VirtualProtect(res, map_size, PAGE_EXECUTE_READWRITE, ctypes.byref(old)) # ignore errors, just try From fijal at codespeak.net Wed May 14 15:11:43 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 14 May 2008 15:11:43 +0200 (CEST) Subject: [pypy-svn] r54733 - pypy/dist/pypy/jit/codegen/i386 Message-ID: <20080514131143.C8BA02A00DE@codespeak.net> Author: fijal Date: Wed May 14 15:11:42 2008 New Revision: 54733 Modified: pypy/dist/pypy/jit/codegen/i386/codebuf_nt.py Log: as much as we need, still don't know how to get kernel32 Modified: pypy/dist/pypy/jit/codegen/i386/codebuf_nt.py ============================================================================== --- pypy/dist/pypy/jit/codegen/i386/codebuf_nt.py (original) +++ pypy/dist/pypy/jit/codegen/i386/codebuf_nt.py Wed May 14 15:11:42 2008 @@ -2,7 +2,7 @@ from pypy.rpython.tool.rffi_platform import ConstantInteger from pypy.rpython.tool.rffi_platform import SimpleType from pypy.translator.tool.cbuild import ExternalCompilationInfo -from pypy.rpython.lltypesystem import rffi +from pypy.rpython.lltypesystem import rffi, lltype raise ImportError @@ -45,9 +45,9 @@ PAGE_EXECUTE_READWRITE) if not res: raise MemoryError - XXX # rewrite - old = DWORD() - VirtualProtect(res, map_size, PAGE_EXECUTE_READWRITE, ctypes.byref(old)) + arg = lltype.malloc(DWORD_P, 1, zero=True, flavor='raw') + VirtualProtect(res, map_size, PAGE_EXECUTE_READWRITE, arg) + lltype.free(arg, flavor='raw') # ignore errors, just try return res From antocuni at codespeak.net Wed May 14 15:41:13 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 14 May 2008 15:41:13 +0200 (CEST) Subject: [pypy-svn] r54734 - pypy/branch/oo-jit/pypy/translator/cli Message-ID: <20080514134113.98868168561@codespeak.net> Author: antocuni Date: Wed May 14 15:41:10 2008 New Revision: 54734 Modified: pypy/branch/oo-jit/pypy/translator/cli/dotnet.py Log: create real .NET arrays instead of python lists Modified: pypy/branch/oo-jit/pypy/translator/cli/dotnet.py ============================================================================== --- pypy/branch/oo-jit/pypy/translator/cli/dotnet.py (original) +++ pypy/branch/oo-jit/pypy/translator/cli/dotnet.py Wed May 14 15:41:10 2008 @@ -508,11 +508,23 @@ return hop.genop('same_as', [v_obj], hop.r_result.lowleveltype) def new_array(type, length): - return [None] * length + # PythonNet doesn't provide a straightforward way to create arrays, + # let's use reflection instead + + # hack to produce the array type name from the member type name + typename = type._INSTANCE._assembly_qualified_name + parts = typename.split(',') + parts[0] = parts[0] + '[]' + typename = ','.join(parts) + t = PythonNet.System.Type.GetType(typename) + ctor = t.GetConstructors()[0] + return ctor.Invoke([length]) def init_array(type, *args): - # PythonNet doesn't provide a straightforward way to create arrays... fake it with a list - return list(args) + array = new_array(type, len(args)) + for i, arg in enumerate(args): + array[i] = arg + return array class Entry(ExtRegistryEntry): _about_ = new_array From antocuni at codespeak.net Wed May 14 16:14:42 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 14 May 2008 16:14:42 +0200 (CEST) Subject: [pypy-svn] r54737 - pypy/branch/oo-jit/pypy/jit/codegen/cli/test Message-ID: <20080514141442.4512F16853F@codespeak.net> Author: antocuni Date: Wed May 14 16:14:41 2008 New Revision: 54737 Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_interpreter.py Log: put a workaround for a mono bug; after this, a lot of tests pass out of the box Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_interpreter.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_interpreter.py (original) +++ pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_interpreter.py Wed May 14 16:14:41 2008 @@ -5,41 +5,41 @@ class TestRainbowCli(RainbowTest): RGenOp = RCliGenOp - RGenOp = RDumpGenOp # for the individual tests see # ====> ../../../rainbow/test/test_interpreter.py + def _invoke(self, generated, residualargs): + + # mono sucks; if we call the generated function directly, + # sometimes the result is wrong (e.g. test_simple_fixed + # fails). If we call it by DynamicInvoke, the result is + # usually correct but from time to time it randomly explodes + # with a TargetParameterCountException. + + # Workaround: first, try to run it by DynamicInvoke; if it + # fails, run it directly/ + from pypy.translator.cli.dotnet import PythonNet + try: + return generated.DynamicInvoke(residualargs) + except PythonNet.System.Reflection.TargetParameterCountException: + return generated(*residualargs) + def run_generated(self, writer, generated, residualargs, **kwds): if 'check_raises' not in kwds: - res = generated.DynamicInvoke(residualargs) + return self._invoke(generated, residualargs) else: assert False, 'TODO' - return res def check_insns(self, expected=None, **counts): "Cannot check instructions in the generated assembler." + def test_simple_opt_const_propagation1(self): + py.test.skip('mono crash') + def skip(self): py.test.skip('in progress') - test_simple_opt_const_propagation1 = skip - test_simple_opt_const_propagation2 = skip - #test_red_switch = skip - test_merge = skip - test_loop_merging = skip - test_loop_merging2 = skip - test_two_loops_merging = skip - test_green_across_split = skip - test_merge_const_before_return = skip - test_merge_3_redconsts_before_return = skip - test_merge_const_at_return = skip - test_call_4 = skip - test_call_5 = skip - test_call_6 = skip - test_green_call = skip - test_green_call_void_return = skip - test_split_on_green_return = skip test_simple_struct = skip test_complex_struct = skip test_simple_array = skip From antocuni at codespeak.net Wed May 14 16:23:40 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 14 May 2008 16:23:40 +0200 (CEST) Subject: [pypy-svn] r54738 - pypy/branch/oo-jit/pypy/jit/codegen/cli/test Message-ID: <20080514142340.BEFDC168551@codespeak.net> Author: antocuni Date: Wed May 14 16:23:40 2008 New Revision: 54738 Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_interpreter.py Log: some more tests pass Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_interpreter.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_interpreter.py (original) +++ pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_interpreter.py Wed May 14 16:23:40 2008 @@ -37,19 +37,23 @@ def test_simple_opt_const_propagation1(self): py.test.skip('mono crash') + def test_red_propagate(self): + py.test.skip('mono crash') + def skip(self): py.test.skip('in progress') + # delegate type not supported during testing test_simple_struct = skip test_complex_struct = skip + test_degenerate_with_voids = skip + test_green_with_side_effects = skip + + # tests still bound to lltype test_simple_array = skip test_arraysize = skip - test_degenerate_with_voids = skip - test_red_virtual_container = skip test_setarrayitem = skip - test_red_propagate = skip - test_merge_structures = skip - test_green_with_side_effects = skip + test_compile_time_const_tuple = skip test_green_deepfrozen_oosend = skip test_direct_oosend_with_green_self = skip From afa at codespeak.net Wed May 14 16:57:44 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Wed, 14 May 2008 16:57:44 +0200 (CEST) Subject: [pypy-svn] r54739 - pypy/dist/pypy/jit/codegen/i386 Message-ID: <20080514145744.EA30C168510@codespeak.net> Author: afa Date: Wed May 14 16:57:43 2008 New Revision: 54739 Modified: pypy/dist/pypy/jit/codegen/i386/codebuf_nt.py Log: Port codebuf to win32. Tests pass. Modified: pypy/dist/pypy/jit/codegen/i386/codebuf_nt.py ============================================================================== --- pypy/dist/pypy/jit/codegen/i386/codebuf_nt.py (original) +++ pypy/dist/pypy/jit/codegen/i386/codebuf_nt.py Wed May 14 16:57:43 2008 @@ -1,15 +1,15 @@ -from pypy.rpython.tool import rffi_pltform +from pypy.rpython.tool import rffi_platform from pypy.rpython.tool.rffi_platform import ConstantInteger from pypy.rpython.tool.rffi_platform import SimpleType from pypy.translator.tool.cbuild import ExternalCompilationInfo from pypy.rpython.lltypesystem import rffi, lltype -raise ImportError +eci = ExternalCompilationInfo( + includes = ["windows.h"] + ) class CConfig: - _compilation_info_ = ExternalCompilationInfo( - includes = "windows.h" - ) + _compilation_info_ = eci SIZE_T = SimpleType('SIZE_T', rffi.LONG) DWORD = SimpleType('DWORD', rffi.LONG) @@ -19,33 +19,32 @@ MEM_RELEASE = ConstantInteger('MEM_RELEASE') PAGE_EXECUTE_READWRITE = ConstantInteger('PAGE_EXECUTE_READWRITE') -globals().update(ctypes_platform.configure(CConfig)) +globals().update(rffi_platform.configure(CConfig)) -# cannot use c_void_p as return value of functions :-( - -# XXX how to get kernel32? -VirtualAlloc = ctypes.windll.kernel32.VirtualAlloc -VirtualAlloc.argtypes = [rffi.VOIDP, rffi.SIZE_T, DWORD, DWORD] -VirtualAlloc.restype = rffi.VOIDP - -DWORD_P = rffi.CArrayPtr(DWORD) -VirtualProtect = ctypes.windll.kernel32.VirtualProtect -VirtualProtect.argtypes = [rffi.VOIDP, rffi.SIZE_T, DWORD, DWORD_P] -VirtualProtect.restype = BOOL - -VirtualFree = ctypes.windll.kernel32.VirtualFree -VirtualFree.argtypes = [rffi.VOIDP, rffi.SIZE_T, DWORD] -VirtualFree.restype = BOOL +def external(name, args, result): + return rffi.llexternal(name, args, result, compilation_info=eci, + calling_conv='win') + +DWORDP = rffi.CArrayPtr(DWORD) +PTR = rffi.VOIDP + +# kernel32 is already part of the ExternalCompilationInfo +VirtualAlloc = external('VirtualAlloc', + [rffi.VOIDP, rffi.SIZE_T, DWORD, DWORD], rffi.VOIDP) +VirtualProtect = external('VirtualProtect', + [rffi.VOIDP, rffi.SIZE_T, DWORD, DWORDP], BOOL) +VirtualFree = external('VirtualFree', + [rffi.VOIDP, rffi.SIZE_T, DWORD], BOOL) # ____________________________________________________________ def alloc(map_size): - null = lltype.nullptr(rffi.VOIDP) + null = lltype.nullptr(rffi.VOIDP.TO) res = VirtualAlloc(null, map_size, MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE) if not res: raise MemoryError - arg = lltype.malloc(DWORD_P, 1, zero=True, flavor='raw') + arg = lltype.malloc(DWORDP.TO, 1, zero=True, flavor='raw') VirtualProtect(res, map_size, PAGE_EXECUTE_READWRITE, arg) lltype.free(arg, flavor='raw') # ignore errors, just try From antocuni at codespeak.net Wed May 14 20:50:12 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 14 May 2008 20:50:12 +0200 (CEST) Subject: [pypy-svn] r54740 - in pypy/dist/pypy/objspace/std: . test Message-ID: <20080514185012.BCBF0168440@codespeak.net> Author: antocuni Date: Wed May 14 20:50:09 2008 New Revision: 54740 Modified: pypy/dist/pypy/objspace/std/dicttype.py pypy/dist/pypy/objspace/std/test/test_dictobject.py Log: when a subclass of dict overrides __setitem__, CPython doesn't always call it, even in a completely inconsistent way. This checkin makes pypy as buggy as CPython --This line, and those below, will be ignored-- M std/dicttype.py M std/test/test_dictobject.py Modified: pypy/dist/pypy/objspace/std/dicttype.py ============================================================================== --- pypy/dist/pypy/objspace/std/dicttype.py (original) +++ pypy/dist/pypy/objspace/std/dicttype.py Wed May 14 20:50:09 2008 @@ -57,13 +57,17 @@ # gateway is imported in the stdtypedef module app = gateway.applevel(''' + # in the following functions we use dict.__setitem__ instead of + # d[k]=... because when a subclass of dict override __setitem__, + # CPython does not call it when doing builtin operations. + def update1(d, o): if hasattr(o, 'keys'): for k in o.keys(): - d[k] = o[k] + dict.__setitem__(d, k, o[k]) else: for k,v in o: - d[k] = v + dict.__setitem__(d, k, v) def update(d, *args, **kwargs): len_args = len(args) @@ -93,7 +97,7 @@ if k in d: return d[k] else: - d[k] = v + dict.__setitem__(d, k, v) return v def pop(d, k, defaults): # XXX defaults is actually *defaults Modified: pypy/dist/pypy/objspace/std/test/test_dictobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/test/test_dictobject.py (original) +++ pypy/dist/pypy/objspace/std/test/test_dictobject.py Wed May 14 20:50:09 2008 @@ -355,6 +355,25 @@ assert repr(D()) == 'hi' assert str(D()) == 'hi' + def test_overridden_setitem(self): + class D(dict): + def __setitem__(self, key, value): + dict.__setitem__(self, key, 42) + d = D([('x', 'foo')], y = 'bar') + assert d['x'] == 'foo' + assert d['y'] == 'bar' + d.setdefault('z', 'baz') + assert d['z'] == 'baz' + d.update({'w': 'foobar'}) + assert d['w'] == 'foobar' + d = d.copy() + assert d['x'] == 'foo' + + d3 = D.fromkeys(['x', 'y'], 'foo') + assert d3['x'] == 42 + assert d3['y'] == 42 + + # the minimal 'space' needed to use a W_DictObject class FakeSpace: def hash_w(self, obj): From xoraxax at codespeak.net Thu May 15 00:16:25 2008 From: xoraxax at codespeak.net (xoraxax at codespeak.net) Date: Thu, 15 May 2008 00:16:25 +0200 (CEST) Subject: [pypy-svn] r54743 - pypy/extradoc/sprintinfo/berlin-2008 Message-ID: <20080514221625.38E291683F3@codespeak.net> Author: xoraxax Date: Thu May 15 00:16:24 2008 New Revision: 54743 Modified: pypy/extradoc/sprintinfo/berlin-2008/people.txt Log: Added my dates. Will arrive on 16th in the late evening, will depart on Sunday evening. Modified: pypy/extradoc/sprintinfo/berlin-2008/people.txt ============================================================================== --- pypy/extradoc/sprintinfo/berlin-2008/people.txt (original) +++ pypy/extradoc/sprintinfo/berlin-2008/people.txt Thu May 15 00:16:24 2008 @@ -18,6 +18,7 @@ Armin Rigo 14-22(noon) private, thanks Stephan Carl Friedrich Bolz 14-22 Die Fabrik Antonio Cuni 19-24 A&O Hotel Mitte +Alexander Schremmer 16(night)-18 www.singer109.com ==================== ============== ======================= People on the following list were present at previous sprints: @@ -39,7 +40,6 @@ Richard Emslie ? ? Johan Hahn ? ? Niko Matsakis ? ? -Alexander Schremmer ? ? Anders Chrigstroem ? ? Michael Hudson ? ? Niko Matsakis ? ? From cami at codespeak.net Thu May 15 10:52:40 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Thu, 15 May 2008 10:52:40 +0200 (CEST) Subject: [pypy-svn] r54744 - in pypy/branch/gameboy-emulator/pypy: lang/gameboy lang/gameboy/test translator/goal Message-ID: <20080515085240.1F824168447@codespeak.net> Author: cami Date: Thu May 15 10:52:38 2008 New Revision: 54744 Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboyImplementation.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/serial.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cartridge.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/video.py pypy/branch/gameboy-emulator/pypy/translator/goal/targetgbrom4.py Log: traintravel office resluts commited Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py Thu May 15 10:52:38 2008 @@ -50,6 +50,7 @@ self.mbc.write(address, data) def load(self, cartridge): + assert isinstance(cartridge, Cartridge) self.cartridge = cartridge self.rom = self.cartridge.read() self.check_rom() @@ -147,7 +148,7 @@ self.load(file) def reset(self): - self.cartridge_name = None + #self.cartridge_name = None self.cartridge_file_path = None self.cartridge_file = None self.battery_name = None @@ -155,21 +156,21 @@ self.battery_file = None - def load(self, cartridge_file_path): - cartridge_file_path = str(cartridge_file_path) - self.cartridge_file_path = cartridge_file_path - self.cartridge_name = os.path.basename(self.cartridge_file_path) - self.cartridge_file = open(cartridge_file_path) - self._load_battery(cartridge_file_path) - - - def _load_battery(self, cartridge_file_path): - self.battery_file_path = self._create_battery_file_path(cartridge_file_path) + def load(self, cartridge_path): + cartridge_path = str(cartridge_path) + self.cartridge_file_path = cartridge_path + #self.cartridge_name = os.path.basename(self.cartridge_file_path) + self.cartridge_file = file(cartridge_path, "r") + self.load_battery(cartridge_path) + + cartridge_path + def load_battery(self, cartridge_file_path): + self.battery_file_path = self.create_battery_file_path(cartridge_path) self.battery_name = os.path.basename(self.battery_file_path) if self.has_battery(): self.battery_file = open(self.battery_file_path) - def _create_battery_file_path(self, cartridge_file_path): + def create_battery_file_path(self, cartridge_file_path): if cartridge_file_path.endswith(constants.CARTRIDGE_FILE_EXTENSION): return cartridge_file_path.replace(constants.CARTRIDGE_FILE_EXTENSION, constants.BATTERY_FILE_EXTENSION) Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboyImplementation.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboyImplementation.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboyImplementation.py Thu May 15 10:52:38 2008 @@ -1,17 +1,17 @@ #!/usr/bin/env python - +import time import pyglet pyglet.options['audio'] = ('openal', 'silent') -from pyglet import window -from pyglet import media -from pyglet import image +from pyglet import window +from pyglet import media +from pyglet import image from pyglet.window import key from pypy.lang.gameboy.gameboy import * from pypy.lang.gameboy.joypad import JoypadDriver -from pypy.lang.gameboy.video import VideoDriver -from pypy.lang.gameboy.sound import SoundDriver +from pypy.lang.gameboy.video import VideoDriver +from pypy.lang.gameboy.sound import SoundDriver # GAMEBOY ---------------------------------------------------------------------- @@ -35,7 +35,9 @@ def mainLoop(self): while not self.win.has_exit: - pass + print "i" + self.emulate(5) + time.sleep(0.01) # VIDEO DRIVER ----------------------------------------------------------------- @@ -51,6 +53,9 @@ def create_image_buffer(self): self.buffers = image.get_buffer_manager() self.image_buffer = self.buffers.get_color_buffer() + self.buffer_image_data = self.image_buffer.image_data + self.buffer_image_data.format = "RGB" + self.pixel_buffer = self.buffer_image_data.data def on_resize(self, width, height): pass @@ -59,9 +64,15 @@ self.win.set_size(self.width, self.height) def update_display(self): + self.buffer_image_data.data = map(self.pixel_to_byte, self.pixel_buffer) self.image_buffer.blit(0, 0) self.win.flip() + def pixel_to_byte(self, int_number): + return struct.pack("B", (int_number) & 0xFF, + (int_number >> 8) & 0xFF, + (int_number >> 16) & 0xFF) + # JOYPAD DRIVER ---------------------------------------------------------------- @@ -87,12 +98,12 @@ self.win.on_key_press = self.on_key_press self.win.on_key_release = self.on_key_press - def on_key_press(symbol, modifiers): + def on_key_press(self, symbol, modifiers): pressButtonFunction = self.get_button_handler(symbol, modifiers) if pressButtonFunction != None: pressButtonFunction(True) - def on_key_release(symbol, modifiers): + def on_key_release(self, symbol, modifiers): pressButtonFunction = self.get_button_handler(symbol, modifiers) if pressButtonFunction != None: pressButtonFunction(False) @@ -132,12 +143,7 @@ # ============================================================================== -if __name__ == '__main__': - entry_point() - - - -def entry_point(args): +def entry_point(args=None): gameboy = GameBoyImplementation() @@ -145,3 +151,6 @@ def target(*args): return entry_point, None + +if __name__ == '__main__': + entry_point() \ No newline at end of file Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/serial.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/serial.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/serial.py Thu May 15 10:52:38 2008 @@ -14,7 +14,7 @@ self.reset() def reset(self): - self.cycles = constants.SERIAL_CLOCK + self.cycles = int(constants.SERIAL_CLOCK) self.sb = 0x00 self.sc = 0x00 Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cartridge.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cartridge.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cartridge.py Thu May 15 10:52:38 2008 @@ -43,7 +43,7 @@ def test_cartridge_init(): cartridge = get_cartridge() - assert cartridge.cartridge_name is None + #assert cartridge.cartridge_name is None assert cartridge.cartridge_file_path is None assert cartridge.cartridge_file is None @@ -58,7 +58,7 @@ romFilePath = ROM_PATH+"/rom1/"+romName cartridge.load(romFilePath) - assert cartridge.cartridge_name == romName + #assert cartridge.cartridge_name == romName assert cartridge.cartridge_file_path == romFilePath assert cartridge.cartridge_file is not None Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/video.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/video.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/video.py Thu May 15 10:52:38 2008 @@ -478,7 +478,7 @@ self.objects[rightmost] = data def draw_tiles(self, x, tileMap, tileData): - while (x < 168): + while x < 168: if (self.control & 0x10) != 0: tile = self.vram[tileMap] & 0xFF else: @@ -489,7 +489,7 @@ def get_pattern(self, address): pattern = self.vram[address] & 0xFF - pattern +=(self.vram[address + 1] & 0xFF) << 8 + pattern += (self.vram[address + 1] & 0xFF) << 8 return pattern def draw_object(self, setter): @@ -585,8 +585,8 @@ class VideoDriver(object): def __init__(self): - self.width = constants.GAMEBOY_SCREEN_WIDTH - self.height = constants.GAMEBOY_SCREEN_HEIGHT + self.width = int(constants.GAMEBOY_SCREEN_WIDTH) + self.height = int(constants.GAMEBOY_SCREEN_HEIGHT) self.clear_pixels() def clear_pixels(self): Modified: pypy/branch/gameboy-emulator/pypy/translator/goal/targetgbrom4.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/translator/goal/targetgbrom4.py (original) +++ pypy/branch/gameboy-emulator/pypy/translator/goal/targetgbrom4.py Thu May 15 10:52:38 2008 @@ -23,13 +23,13 @@ def entry_point(argv): - #if len(argv) > 1: - # filename = argv[1] - #else: - # print "usage:", argv[0], "" - # return -1 + if len(argv) > 1: + filename = argv[1] + else: + filename = ROM_PATH+"/rom4/rom4.gb" gameBoy = GameBoy() - gameBoy.load_cartridge_file(ROM_PATH+"/rom4/rom4.gb")#filename) + #gameBoy.load_cartridge_file(ROM_PATH+"/rom4/rom4.gb")#filename) + gameBoy.load_cartridge_file(str(filename)) gameBoy.emulate(EMULATION_CYCLES) # _____ Define and setup target ___ From afa at codespeak.net Thu May 15 11:03:48 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Thu, 15 May 2008 11:03:48 +0200 (CEST) Subject: [pypy-svn] r54745 - in pypy/dist/pypy/translator/tool: . test Message-ID: <20080515090348.E86A7168447@codespeak.net> Author: afa Date: Thu May 15 11:03:47 2008 New Revision: 54745 Modified: pypy/dist/pypy/translator/tool/cbuild.py pypy/dist/pypy/translator/tool/test/test_cbuild.py Log: Add the eventual eci.separate_module_files when compiling a standalone executable, so that rffi_platform.configure may compile configuration tests with separate_module_sources and separate_module_files. Used by the libffi module. Also, better detection of debug mode on windows: Purify renames the original python.exe program. And let test_cbuild pass on win32. Modified: pypy/dist/pypy/translator/tool/cbuild.py ============================================================================== --- pypy/dist/pypy/translator/tool/cbuild.py (original) +++ pypy/dist/pypy/translator/tool/cbuild.py Thu May 15 11:03:47 2008 @@ -317,7 +317,8 @@ cmdobj = build_shared_library(dist) cmdobj.inplace = True cmdobj.force = True - if sys.platform == 'win32' and sys.executable.endswith('_d.exe'): + if (sys.platform == 'win32' + and sys.executable.lower().endswith('_d.exe')): cmdobj.debug = True dist.command_obj["build_ext"] = cmdobj dist.have_run["build_ext"] = 0 @@ -479,8 +480,10 @@ linker_exe linker_so'''.split(): compiler.executables[c][0] = self.compiler_exe compiler.spawn = log_spawned_cmd(compiler.spawn) + self.eci = self.eci.convert_sources_to_files() + filenames = self.cfilenames + list(self.eci.separate_module_files) objects = [] - for cfile in self.cfilenames: + for cfile in filenames: cfile = py.path.local(cfile) old = cfile.dirpath().chdir() try: Modified: pypy/dist/pypy/translator/tool/test/test_cbuild.py ============================================================================== --- pypy/dist/pypy/translator/tool/test/test_cbuild.py (original) +++ pypy/dist/pypy/translator/tool/test/test_cbuild.py Thu May 15 11:03:47 2008 @@ -45,9 +45,12 @@ { printf("%f\\n", pow(2.0, 2.0)); }''') - eci = ExternalCompilationInfo( - libraries = ['m'], - ) + if sys.platform != 'win32': + eci = ExternalCompilationInfo( + libraries = ['m'], + ) + else: + eci = ExternalCompilationInfo() output = build_executable([c_file], eci) p = Popen(output, stdout=PIPE, stderr=STDOUT) p.wait() @@ -109,7 +112,8 @@ int get() { return 42; - }'''] + }'''], + export_symbols = ['get'] ) neweci = eci.compile_shared_lib() assert len(neweci.libraries) == 1 From afa at codespeak.net Thu May 15 11:19:20 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Thu, 15 May 2008 11:19:20 +0200 (CEST) Subject: [pypy-svn] r54746 - pypy/dist/pypy/rpython/lltypesystem/test Message-ID: <20080515091920.459DB16843F@codespeak.net> Author: afa Date: Thu May 15 11:19:19 2008 New Revision: 54746 Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_rffi.py Log: This test crashes on some configurations. Explain why it is broken, and skip it. I'm not sure what this function tries to test. If it's only about a string allocated by the external function, then we could just leak this pointer. Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_rffi.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/test/test_rffi.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/test/test_rffi.py Thu May 15 11:19:19 2008 @@ -69,6 +69,12 @@ assert xf() == 3 def test_string_reverse(self): + # XXX This test crashes with a debug build + # (when python is built WITH_PYMALLOC and PYMALLOC_DEBUG): + # lltype.free calls OP_RAW_FREE() == PyObject_Free(), + # but the buffer comes from a malloc() + if sys.platform == 'win32' and 'python_d' in sys.executable: + py.test.skip("Crash with a debug build") c_source = py.code.Source(""" #include From afa at codespeak.net Thu May 15 11:33:20 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Thu, 15 May 2008 11:33:20 +0200 (CEST) Subject: [pypy-svn] r54747 - in pypy/dist/pypy: rlib rlib/test translator/c/src/libffi_msvc Message-ID: <20080515093320.40974168452@codespeak.net> Author: afa Date: Thu May 15 11:33:19 2008 New Revision: 54747 Added: pypy/dist/pypy/translator/c/src/libffi_msvc/ pypy/dist/pypy/translator/c/src/libffi_msvc/README.pypy pypy/dist/pypy/translator/c/src/libffi_msvc/ffi.c pypy/dist/pypy/translator/c/src/libffi_msvc/ffi.h pypy/dist/pypy/translator/c/src/libffi_msvc/ffi_common.h pypy/dist/pypy/translator/c/src/libffi_msvc/fficonfig.h pypy/dist/pypy/translator/c/src/libffi_msvc/ffitarget.h pypy/dist/pypy/translator/c/src/libffi_msvc/prep_cif.c pypy/dist/pypy/translator/c/src/libffi_msvc/pypy_ffi.c pypy/dist/pypy/translator/c/src/libffi_msvc/types.c pypy/dist/pypy/translator/c/src/libffi_msvc/win32.c Modified: pypy/dist/pypy/rlib/libffi.py pypy/dist/pypy/rlib/test/test_libffi.py Log: Port rlib/libffi to win32. Added the directory translator/c/src/libffi_msvc which contains a copy of the CPython Modules/_ctypes/libffi_msvc. Together with the pypy_ffi.c file, they build the win32/msvc version of the ffi standard library. test_libffi now passes on win32. Someone should check that I did not break anything on other platforms. Modified: pypy/dist/pypy/rlib/libffi.py ============================================================================== --- pypy/dist/pypy/rlib/libffi.py (original) +++ pypy/dist/pypy/rlib/libffi.py Thu May 15 11:33:19 2008 @@ -10,27 +10,49 @@ from pypy.tool.autopath import pypydir from pypy.translator.tool.cbuild import ExternalCompilationInfo import py +import os -includes = ['dlfcn.h', 'ffi.h'] -include_dirs = [] -pot_incl = py.path.local('/usr/include/libffi') -if pot_incl.check(): - include_dirs.append(str(pot_incl)) -lib_dirs = [] -pot_lib = py.path.local('/usr/lib/libffi') -if pot_lib.check(): - lib_dirs.append(str(pot_lib)) +_MS_WINDOWS = os.name == "nt" -FFI_TYPE_P = lltype.Ptr(lltype.ForwardReference()) -FFI_TYPE_PP = rffi.CArrayPtr(FFI_TYPE_P) +if not _MS_WINDOWS: + includes = ['dlfcn.h', 'ffi.h'] + include_dirs = [] + pot_incl = py.path.local('/usr/include/libffi') + if pot_incl.check(): + include_dirs.append(str(pot_incl)) + lib_dirs = [] + pot_lib = py.path.local('/usr/lib/libffi') + if pot_lib.check(): + lib_dirs.append(str(pot_lib)) -class CConfig: - _compilation_info_ = ExternalCompilationInfo( + eci = ExternalCompilationInfo( includes = includes, libraries = ['ffi', 'dl'], include_dirs = include_dirs, library_dirs = lib_dirs, ) +else: + libffidir = py.path.local(pypydir).join('translator', 'c', 'src', 'libffi_msvc') + eci = ExternalCompilationInfo( + includes = ['ffi.h', 'windows.h'], + libraries = ['kernel32'], + include_dirs = [libffidir], + separate_module_files = [libffidir.join('ffi.c'), + libffidir.join('prep_cif.c'), + libffidir.join('win32.c'), + libffidir.join('pypy_ffi.c'), + ], + export_symbols = ['ffi_call', 'ffi_prep_cif', 'ffi_prep_closure'], + ) + +if not rffi_platform.check_eci(eci): + raise ImportError("cannot find an installed 'libffi' library") + +FFI_TYPE_P = lltype.Ptr(lltype.ForwardReference()) +FFI_TYPE_PP = rffi.CArrayPtr(FFI_TYPE_P) + +class CConfig: + _compilation_info_ = eci RTLD_LOCAL = rffi_platform.DefinedConstantInteger('RTLD_LOCAL') RTLD_GLOBAL = rffi_platform.DefinedConstantInteger('RTLD_GLOBAL') @@ -39,6 +61,8 @@ 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') + if _MS_WINDOWS: + FFI_STDCALL = rffi_platform.ConstantInteger('FFI_STDCALL') FFI_TYPE_STRUCT = rffi_platform.ConstantInteger('FFI_TYPE_STRUCT') @@ -51,8 +75,9 @@ ffi_closure = rffi_platform.Struct('ffi_closure', []) -if not rffi_platform.check_eci(CConfig._compilation_info_): - raise ImportError("cannot find an installed 'libffi' library") + if _MS_WINDOWS: + DWORD = rffi_platform.SimpleType("DWORD", rffi.UINT) + BOOL = rffi_platform.SimpleType("BOOL", rffi.LONG) def add_simple_type(type_name): for name in ['size', 'alignment', 'type']: @@ -124,24 +149,88 @@ } def external(name, args, result, **kwds): - return rffi.llexternal(name, args, result, - compilation_info=CConfig._compilation_info_, **kwds) + return rffi.llexternal(name, args, result, compilation_info=eci, **kwds) + +def winexternal(name, args, result): + return rffi.llexternal(name, args, result, compilation_info=eci, calling_conv='win') + +if not _MS_WINDOWS: + c_dlopen = external('dlopen', [rffi.CCHARP, rffi.INT], rffi.VOIDP, + _nowrapper=True) + 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): + """ Wrapper around C-level dlopen + """ + 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: + raise OSError(-1, dlerror()) + 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 + +if _MS_WINDOWS: + LoadLibrary = winexternal('LoadLibraryA', [rffi.CCHARP], rffi.VOIDP) + GetProcAddress = winexternal('GetProcAddress', [rffi.VOIDP, rffi.CCHARP], rffi.VOIDP) + FreeLibrary = winexternal('FreeLibrary', [rffi.VOIDP], cConfig.BOOL) + GetLastError = winexternal('GetLastError', [], cConfig.DWORD) + + def dlopen(name): + res = LoadLibrary(name) + if not res: + # XXX format error message + raise WindowsError(2, GetLastError()) + return res + + def dlclose(handle): + res = FreeLibrary(handle) + if res: + return -1 + else: + return 0 + + def dlsym(handle, name): + res = GetProcAddress(handle, name) + if not res: + raise KeyError(name) + # XXX rffi.cast here... + return res -c_dlopen = external('dlopen', [rffi.CCHARP, rffi.INT], rffi.VOIDP, - _nowrapper=True) -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 FFI_OK = cConfig.FFI_OK FFI_BAD_TYPEDEF = cConfig.FFI_BAD_TYPEDEF FFI_DEFAULT_ABI = rffi.cast(rffi.USHORT, cConfig.FFI_DEFAULT_ABI) +if _MS_WINDOWS: + FFI_STDCALL = rffi.cast(rffi.USHORT, cConfig.FFI_STDCALL) FFI_TYPE_STRUCT = rffi.cast(rffi.USHORT, cConfig.FFI_TYPE_STRUCT) -FFI_CIFP = rffi.COpaquePtr('ffi_cif', compilation_info=CConfig. - _compilation_info_) +FFI_CIFP = rffi.COpaquePtr('ffi_cif', compilation_info=eci) FFI_CLOSUREP = lltype.Ptr(cConfig.ffi_closure) @@ -157,36 +246,6 @@ CALLBACK_TP, rffi.VOIDP], rffi.INT) -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): - """ Wrapper around C-level dlopen - """ - 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: - raise OSError(-1, dlerror()) - return res - -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 make_struct_ffitype(size, aligment): tp = lltype.malloc(FFI_TYPE_P.TO, flavor='raw') tp.c_type = FFI_TYPE_STRUCT @@ -233,7 +292,7 @@ userdata.callback(ll_args, ll_res, userdata) # heap for closures -from pypy.jit.codegen.i386 import codebuf_posix +from pypy.jit.codegen.i386.codebuf import memhandler CHUNK = 4096 CLOSURES = rffi.CArrayPtr(FFI_CLOSUREP.TO) @@ -244,7 +303,7 @@ self.free_list = lltype.nullptr(rffi.VOIDP.TO) def _more(self): - chunk = rffi.cast(CLOSURES, codebuf_posix.alloc(CHUNK)) + chunk = rffi.cast(CLOSURES, memhandler.alloc(CHUNK)) count = CHUNK//rffi.sizeof(FFI_CLOSUREP.TO) for i in range(count): rffi.cast(rffi.VOIDPP, chunk)[0] = self.free_list @@ -263,13 +322,15 @@ self.free_list = rffi.cast(rffi.VOIDP, p) closureHeap = ClosureHeap() - + +FUNCFLAG_STDCALL = 0 +FUNCFLAG_CDECL = 1 # for WINAPI calls class AbstractFuncPtr(object): ll_cif = lltype.nullptr(FFI_CIFP.TO) ll_argtypes = lltype.nullptr(FFI_TYPE_PP.TO) - def __init__(self, name, argtypes, restype): + def __init__(self, name, argtypes, restype, flags=0): self.name = name self.argtypes = argtypes self.restype = restype @@ -278,7 +339,22 @@ for i in range(argnum): self.ll_argtypes[i] = argtypes[i] self.ll_cif = lltype.malloc(FFI_CIFP.TO, flavor='raw') - res = c_ffi_prep_cif(self.ll_cif, FFI_DEFAULT_ABI, + + if _MS_WINDOWS and (flags & FUNCFLAG_CDECL == 0): + cc = FFI_STDCALL + else: + cc = FFI_DEFAULT_ABI + + if _MS_WINDOWS: + # This little trick works correctly with MSVC. + # It returns small structures in registers + if restype.c_type == FFI_TYPE_STRUCT: + if restype.c_size <= 4: + restype = ffi_type_sint32 + elif restype.c_size <= 8: + restype = ffi_type_sint64 + + res = c_ffi_prep_cif(self.ll_cif, cc, rffi.cast(rffi.UINT, argnum), restype, self.ll_argtypes) if not res == FFI_OK: @@ -300,8 +376,9 @@ # additional_arg should really be a non-heap type like a integer, # it cannot be any kind of movable gc reference - def __init__(self, argtypes, restype, func, additional_arg=0): - AbstractFuncPtr.__init__(self, "callback", argtypes, restype) + def __init__(self, argtypes, restype, func, additional_arg=0, + flags=FUNCFLAG_CDECL): + AbstractFuncPtr.__init__(self, "callback", argtypes, restype, flags) self.ll_closure = closureHeap.alloc() self.ll_userdata = lltype.malloc(USERDATA_P.TO, flavor='raw') self.ll_userdata.callback = rffi.llhelper(CALLBACK_TP, func) @@ -323,8 +400,8 @@ class RawFuncPtr(AbstractFuncPtr): - def __init__(self, name, argtypes, restype, funcsym): - AbstractFuncPtr.__init__(self, name, argtypes, restype) + def __init__(self, name, argtypes, restype, funcsym, flags=0): + AbstractFuncPtr.__init__(self, name, argtypes, restype, flags) self.funcsym = funcsym def call(self, args_ll, ll_result): @@ -343,9 +420,9 @@ ll_args = lltype.nullptr(rffi.VOIDPP.TO) ll_result = lltype.nullptr(rffi.VOIDP.TO) - def __init__(self, name, argtypes, restype, funcsym): + def __init__(self, name, argtypes, restype, funcsym, flags=0): # initialize each one of pointers with null - AbstractFuncPtr.__init__(self, name, argtypes, restype) + AbstractFuncPtr.__init__(self, name, argtypes, restype, flags) self.funcsym = funcsym self.argnum = len(self.argtypes) self.pushed_args = 0 @@ -416,6 +493,8 @@ AbstractFuncPtr.__del__(self) class CDLL: + flags = FUNCFLAG_CDECL + def __init__(self, libname): self.ll_libname = lltype.nullptr(rffi.CCHARP.TO) self.lib = lltype.nullptr(rffi.CCHARP.TO) @@ -424,7 +503,7 @@ def __del__(self): if self.lib: - c_dlclose(self.lib) + dlclose(self.lib) self.lib = lltype.nullptr(rffi.CCHARP.TO) if self.ll_libname: lltype.free(self.ll_libname, flavor='raw') @@ -433,12 +512,14 @@ def getpointer(self, name, argtypes, restype): # these arguments are already casted to proper ffi # structures! - return FuncPtr(name, argtypes, restype, dlsym(self.lib, name)) + return FuncPtr(name, argtypes, restype, dlsym(self.lib, name), + flags=self.flags) def getrawpointer(self, name, argtypes, restype): # these arguments are already casted to proper ffi # structures! - return RawFuncPtr(name, argtypes, restype, dlsym(self.lib, name)) + return RawFuncPtr(name, argtypes, restype, dlsym(self.lib, name), + flags=self.flags) def getaddressindll(self, name): return dlsym(self.lib, name) Modified: pypy/dist/pypy/rlib/test/test_libffi.py ============================================================================== --- pypy/dist/pypy/rlib/test/test_libffi.py (original) +++ pypy/dist/pypy/rlib/test/test_libffi.py Thu May 15 11:33:19 2008 @@ -13,8 +13,8 @@ import time def setup_module(mod): - if not sys.platform.startswith('linux'): - py.test.skip("Fragile tests, linux only by now") + if not sys.platform.startswith(('linux', 'win32')): + py.test.skip("Fragile tests, linux & win32 only by now") for name in type_names: # XXX force this to be seen by ll2ctypes # so that ALLOCATED.clear() clears it @@ -27,10 +27,22 @@ def test_dlopen(self): py.test.raises(OSError, "dlopen(rffi.str2charp('xxxxxxxxxxxx'))") - assert dlopen(rffi.str2charp('/lib/libc.so.6')) + if sys.platform == 'win32': + assert dlopen(rffi.str2charp('kernel32.dll')) + else: + assert dlopen(rffi.str2charp('/lib/libc.so.6')) def get_libc(self): - return CDLL('/lib/libc.so.6') + if sys.platform == 'win32': + return CDLL('msvcrt.dll') + else: + return CDLL('/lib/libc.so.6') + + def get_libm(self): + if sys.platform == 'win32': + return CDLL('msvcrt.dll') + else: + return CDLL('libm.so') def test_library_open(self): lib = self.get_libc() @@ -61,7 +73,7 @@ assert not ALLOCATED def test_call_args(self): - libm = CDLL('libm.so') + libm = self.get_libm() pow = libm.getpointer('pow', [ffi_type_double, ffi_type_double], ffi_type_double) pow.push_arg(2.0) @@ -77,7 +89,7 @@ assert not ALLOCATED def test_wrong_args(self): - libc = CDLL('libc.so.6') + libc = self.get_libc() # XXX assume time_t is long ulong = cast_type_to_ffitype(rffi.ULONG) ctime = libc.getpointer('time', [ffi_type_pointer], ulong) @@ -93,7 +105,7 @@ # allocation check makes no sense, since we've got GcStructs around def test_call_time(self): - libc = CDLL('libc.so.6') + libc = self.get_libc() # XXX assume time_t is long ulong = cast_type_to_ffitype(rffi.ULONG) ctime = libc.getpointer('time', [ffi_type_pointer], ulong) @@ -144,7 +156,7 @@ def test_callback(self): slong = cast_type_to_ffitype(rffi.LONG) - libc = CDLL('libc.so.6') + libc = self.get_libc() qsort = libc.getpointer('qsort', [ffi_type_pointer, slong, slong, ffi_type_pointer], ffi_type_void) @@ -186,7 +198,7 @@ # with pointer casts def f(x, y): - libm = CDLL('libm.so') + libm = self.get_libm() c_pow = libm.getpointer('pow', [ffi_type_double, ffi_type_double], ffi_type_double) c_pow.push_arg(x) c_pow.push_arg(y) @@ -198,7 +210,7 @@ assert res == 16.0 def test_rawfuncptr(self): - libm = CDLL('libm.so') + libm = self.get_libm() pow = libm.getrawpointer('pow', [ffi_type_double, ffi_type_double], ffi_type_double) buffer = lltype.malloc(rffi.DOUBLEP.TO, 3, flavor='raw') @@ -245,7 +257,8 @@ } ''')) - lib_name = compile_c_module([c_file], 'x', ExternalCompilationInfo()) + eci = ExternalCompilationInfo(export_symbols=['sum_x_y']) + lib_name = compile_c_module([c_file], 'x', eci) lib = CDLL(lib_name) @@ -300,7 +313,8 @@ } ''')) - lib_name = compile_c_module([c_file], 'x', ExternalCompilationInfo()) + eci = ExternalCompilationInfo(export_symbols=['give', 'perturb']) + lib_name = compile_c_module([c_file], 'x', eci) lib = CDLL(lib_name) Added: pypy/dist/pypy/translator/c/src/libffi_msvc/README.pypy ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/c/src/libffi_msvc/README.pypy Thu May 15 11:33:19 2008 @@ -0,0 +1,8 @@ +This directory contains the libffi package, copied from the +Modules/_ctypes/libffi_msvc directory of the CPython distribution, +as of relase 2.6a3. + +It was slightly modify to suit pypy needs: +- Py_FatalError was renamed to libffi_fatalerror, in ffi.c +- The file pypy_ffi.c was added, to resolve undefined externals. + Its contents is inspired from the `ctypes.c` file of the CPython module. Added: pypy/dist/pypy/translator/c/src/libffi_msvc/ffi.c ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/c/src/libffi_msvc/ffi.c Thu May 15 11:33:19 2008 @@ -0,0 +1,480 @@ +/* ----------------------------------------------------------------------- + ffi.c - Copyright (c) 1996, 1998, 1999, 2001 Red Hat, Inc. + Copyright (c) 2002 Ranjit Mathew + Copyright (c) 2002 Bo Thorsen + Copyright (c) 2002 Roger Sayle + + x86 Foreign Function Interface + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + ``Software''), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR + OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. + ----------------------------------------------------------------------- */ + +#include +#include + +#include + +/* ffi_prep_args is called by the assembly routine once stack space + has been allocated for the function's arguments */ + +extern void ffi_fatalerror(char *msg); + +/*@-exportheader@*/ +void ffi_prep_args(char *stack, extended_cif *ecif) +/*@=exportheader@*/ +{ + register unsigned int i; + register void **p_argv; + register char *argp; + register ffi_type **p_arg; + + argp = stack; + if (ecif->cif->rtype->type == FFI_TYPE_STRUCT) + { + *(void **) argp = ecif->rvalue; + argp += sizeof(void *); + } + + p_argv = ecif->avalue; + + for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; + i != 0; + i--, p_arg++) + { + size_t z; + + /* Align if necessary */ + if ((sizeof(void *) - 1) & (size_t) argp) + argp = (char *) ALIGN(argp, sizeof(void *)); + + z = (*p_arg)->size; + if (z < sizeof(int)) + { + z = sizeof(int); + switch ((*p_arg)->type) + { + case FFI_TYPE_SINT8: + *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv); + break; + + case FFI_TYPE_UINT8: + *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv); + break; + + case FFI_TYPE_SINT16: + *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv); + break; + + case FFI_TYPE_UINT16: + *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv); + break; + + case FFI_TYPE_SINT32: + *(signed int *) argp = (signed int)*(SINT32 *)(* p_argv); + break; + + case FFI_TYPE_UINT32: + *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv); + break; + + case FFI_TYPE_STRUCT: + *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv); + break; + + default: + FFI_ASSERT(0); + } + } + else + { + memcpy(argp, *p_argv, z); + } + p_argv++; + argp += z; + } + + if (argp - stack > ecif->cif->bytes) + { + ffi_fatalerror("FFI BUG: not enough stack space for arguments"); + } + return; +} + +/* Perform machine dependent cif processing */ +ffi_status ffi_prep_cif_machdep(ffi_cif *cif) +{ + /* Set the return type flag */ + switch (cif->rtype->type) + { + case FFI_TYPE_VOID: + case FFI_TYPE_STRUCT: + case FFI_TYPE_SINT64: + case FFI_TYPE_FLOAT: + case FFI_TYPE_DOUBLE: + case FFI_TYPE_LONGDOUBLE: + cif->flags = (unsigned) cif->rtype->type; + break; + + case FFI_TYPE_UINT64: +#ifdef _WIN64 + case FFI_TYPE_POINTER: +#endif + cif->flags = FFI_TYPE_SINT64; + break; + + default: + cif->flags = FFI_TYPE_INT; + break; + } + + return FFI_OK; +} + +#ifdef _WIN32 +/*@-declundef@*/ +/*@-exportheader@*/ +extern int +ffi_call_SYSV(void (*)(char *, extended_cif *), + /*@out@*/ extended_cif *, + unsigned, unsigned, + /*@out@*/ unsigned *, + void (*fn)()); +/*@=declundef@*/ +/*@=exportheader@*/ + +/*@-declundef@*/ +/*@-exportheader@*/ +extern int +ffi_call_STDCALL(void (*)(char *, extended_cif *), + /*@out@*/ extended_cif *, + unsigned, unsigned, + /*@out@*/ unsigned *, + void (*fn)()); +/*@=declundef@*/ +/*@=exportheader@*/ +#endif + +#ifdef _WIN64 +extern int +ffi_call_AMD64(void (*)(char *, extended_cif *), + /*@out@*/ extended_cif *, + unsigned, unsigned, + /*@out@*/ unsigned *, + void (*fn)()); +#endif + +int +ffi_call(/*@dependent@*/ ffi_cif *cif, + void (*fn)(), + /*@out@*/ void *rvalue, + /*@dependent@*/ void **avalue) +{ + extended_cif ecif; + + ecif.cif = cif; + ecif.avalue = avalue; + + /* If the return value is a struct and we don't have a return */ + /* value address then we need to make one */ + + if ((rvalue == NULL) && + (cif->rtype->type == FFI_TYPE_STRUCT)) + { + /*@-sysunrecog@*/ + ecif.rvalue = alloca(cif->rtype->size); + /*@=sysunrecog@*/ + } + else + ecif.rvalue = rvalue; + + + switch (cif->abi) + { +#if !defined(_WIN64) + case FFI_SYSV: + /*@-usedef@*/ + return ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, + cif->flags, ecif.rvalue, fn); + /*@=usedef@*/ + break; + + case FFI_STDCALL: + /*@-usedef@*/ + return ffi_call_STDCALL(ffi_prep_args, &ecif, cif->bytes, + cif->flags, ecif.rvalue, fn); + /*@=usedef@*/ + break; +#else + case FFI_SYSV: + /*@-usedef@*/ + /* Function call needs at least 40 bytes stack size, on win64 AMD64 */ + return ffi_call_AMD64(ffi_prep_args, &ecif, cif->bytes ? cif->bytes : 40, + cif->flags, ecif.rvalue, fn); + /*@=usedef@*/ + break; +#endif + + default: + FFI_ASSERT(0); + break; + } + return -1; /* theller: Hrm. */ +} + + +/** private members **/ + +static void ffi_prep_incoming_args_SYSV (char *stack, void **ret, + void** args, ffi_cif* cif); +/* This function is jumped to by the trampoline */ + +#ifdef _WIN64 +void * +#else +static void __fastcall +#endif +ffi_closure_SYSV (ffi_closure *closure, int *argp) +{ + // this is our return value storage + long double res; + + // our various things... + ffi_cif *cif; + void **arg_area; + unsigned short rtype; + void *resp = (void*)&res; + void *args = &argp[1]; + + cif = closure->cif; + arg_area = (void**) alloca (cif->nargs * sizeof (void*)); + + /* this call will initialize ARG_AREA, such that each + * element in that array points to the corresponding + * value on the stack; and if the function returns + * a structure, it will re-set RESP to point to the + * structure return address. */ + + ffi_prep_incoming_args_SYSV(args, (void**)&resp, arg_area, cif); + + (closure->fun) (cif, resp, arg_area, closure->user_data); + + rtype = cif->flags; + +#if defined(_WIN32) && !defined(_WIN64) +#ifdef _MSC_VER + /* now, do a generic return based on the value of rtype */ + if (rtype == FFI_TYPE_INT) + { + _asm mov eax, resp ; + _asm mov eax, [eax] ; + } + else if (rtype == FFI_TYPE_FLOAT) + { + _asm mov eax, resp ; + _asm fld DWORD PTR [eax] ; +// asm ("flds (%0)" : : "r" (resp) : "st" ); + } + else if (rtype == FFI_TYPE_DOUBLE) + { + _asm mov eax, resp ; + _asm fld QWORD PTR [eax] ; +// asm ("fldl (%0)" : : "r" (resp) : "st", "st(1)" ); + } + else if (rtype == FFI_TYPE_LONGDOUBLE) + { +// asm ("fldt (%0)" : : "r" (resp) : "st", "st(1)" ); + } + else if (rtype == FFI_TYPE_SINT64) + { + _asm mov edx, resp ; + _asm mov eax, [edx] ; + _asm mov edx, [edx + 4] ; +// asm ("movl 0(%0),%%eax;" +// "movl 4(%0),%%edx" +// : : "r"(resp) +// : "eax", "edx"); + } +#else + /* now, do a generic return based on the value of rtype */ + if (rtype == FFI_TYPE_INT) + { + asm ("movl (%0),%%eax" : : "r" (resp) : "eax"); + } + else if (rtype == FFI_TYPE_FLOAT) + { + asm ("flds (%0)" : : "r" (resp) : "st" ); + } + else if (rtype == FFI_TYPE_DOUBLE) + { + asm ("fldl (%0)" : : "r" (resp) : "st", "st(1)" ); + } + else if (rtype == FFI_TYPE_LONGDOUBLE) + { + asm ("fldt (%0)" : : "r" (resp) : "st", "st(1)" ); + } + else if (rtype == FFI_TYPE_SINT64) + { + asm ("movl 0(%0),%%eax;" + "movl 4(%0),%%edx" + : : "r"(resp) + : "eax", "edx"); + } +#endif +#endif + +#ifdef _WIN64 + /* The result is returned in rax. This does the right thing for + result types except for floats; we have to 'mov xmm0, rax' in the + caller to correct this. + */ + return *(void **)resp; +#endif +} + +/*@-exportheader@*/ +static void +ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, + void **avalue, ffi_cif *cif) +/*@=exportheader@*/ +{ + register unsigned int i; + register void **p_argv; + register char *argp; + register ffi_type **p_arg; + + argp = stack; + + if ( cif->rtype->type == FFI_TYPE_STRUCT ) { + *rvalue = *(void **) argp; + argp += 4; + } + + p_argv = avalue; + + for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++) + { + size_t z; + + /* Align if necessary */ + if ((sizeof(char *) - 1) & (size_t) argp) { + argp = (char *) ALIGN(argp, sizeof(char*)); + } + + z = (*p_arg)->size; + + /* because we're little endian, this is what it turns into. */ + + *p_argv = (void*) argp; + + p_argv++; + argp += z; + } + + return; +} + +/* the cif must already be prep'ed */ +extern void ffi_closure_OUTER(); + +ffi_status +ffi_prep_closure (ffi_closure* closure, + ffi_cif* cif, + void (*fun)(ffi_cif*,void*,void**,void*), + void *user_data) +{ + short bytes; + char *tramp; +#ifdef _WIN64 + int mask; +#endif + FFI_ASSERT (cif->abi == FFI_SYSV); + + if (cif->abi == FFI_SYSV) + bytes = 0; +#if !defined(_WIN64) + else if (cif->abi == FFI_STDCALL) + bytes = cif->bytes; +#endif + else + return FFI_BAD_ABI; + + tramp = &closure->tramp[0]; + +#define BYTES(text) memcpy(tramp, text, sizeof(text)), tramp += sizeof(text)-1 +#define POINTER(x) *(void**)tramp = (void*)(x), tramp += sizeof(void*) +#define SHORT(x) *(short*)tramp = x, tramp += sizeof(short) +#define INT(x) *(int*)tramp = x, tramp += sizeof(int) + +#ifdef _WIN64 + if (cif->nargs >= 1 && + (cif->arg_types[0]->type == FFI_TYPE_FLOAT + || cif->arg_types[0]->type == FFI_TYPE_DOUBLE)) + mask |= 1; + if (cif->nargs >= 2 && + (cif->arg_types[1]->type == FFI_TYPE_FLOAT + || cif->arg_types[1]->type == FFI_TYPE_DOUBLE)) + mask |= 2; + if (cif->nargs >= 3 && + (cif->arg_types[2]->type == FFI_TYPE_FLOAT + || cif->arg_types[2]->type == FFI_TYPE_DOUBLE)) + mask |= 4; + if (cif->nargs >= 4 && + (cif->arg_types[3]->type == FFI_TYPE_FLOAT + || cif->arg_types[3]->type == FFI_TYPE_DOUBLE)) + mask |= 8; + + /* 41 BB ---- mov r11d,mask */ + BYTES("\x41\xBB"); INT(mask); + + /* 48 B8 -------- mov rax, closure */ + BYTES("\x48\xB8"); POINTER(closure); + + /* 49 BA -------- mov r10, ffi_closure_OUTER */ + BYTES("\x49\xBA"); POINTER(ffi_closure_OUTER); + + /* 41 FF E2 jmp r10 */ + BYTES("\x41\xFF\xE2"); + +#else + + /* mov ecx, closure */ + BYTES("\xb9"); POINTER(closure); + + /* mov edx, esp */ + BYTES("\x8b\xd4"); + + /* call ffi_closure_SYSV */ + BYTES("\xe8"); POINTER((char*)&ffi_closure_SYSV - (tramp + 4)); + + /* ret bytes */ + BYTES("\xc2"); + SHORT(bytes); + +#endif + + if (tramp - &closure->tramp[0] > FFI_TRAMPOLINE_SIZE) + ffi_fatalerror("FFI_TRAMPOLINE_SIZE too small in " __FILE__); + + closure->cif = cif; + closure->user_data = user_data; + closure->fun = fun; + + return FFI_OK; +} Added: pypy/dist/pypy/translator/c/src/libffi_msvc/ffi.h ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/c/src/libffi_msvc/ffi.h Thu May 15 11:33:19 2008 @@ -0,0 +1,315 @@ +/* -----------------------------------------------------------------*-C-*- + libffi 2.00-beta - Copyright (c) 1996-2003 Red Hat, Inc. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + ``Software''), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR + OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. + + ----------------------------------------------------------------------- */ + +/* ------------------------------------------------------------------- + The basic API is described in the README file. + + The raw API is designed to bypass some of the argument packing + and unpacking on architectures for which it can be avoided. + + The closure API allows interpreted functions to be packaged up + inside a C function pointer, so that they can be called as C functions, + with no understanding on the client side that they are interpreted. + It can also be used in other cases in which it is necessary to package + up a user specified parameter and a function pointer as a single + function pointer. + + The closure API must be implemented in order to get its functionality, + e.g. for use by gij. Routines are provided to emulate the raw API + if the underlying platform doesn't allow faster implementation. + + More details on the raw and cloure API can be found in: + + http://gcc.gnu.org/ml/java/1999-q3/msg00138.html + + and + + http://gcc.gnu.org/ml/java/1999-q3/msg00174.html + -------------------------------------------------------------------- */ + +#ifndef LIBFFI_H +#define LIBFFI_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Specify which architecture libffi is configured for. */ +//XXX #define X86 + +/* ---- System configuration information --------------------------------- */ + +#include + +#ifndef LIBFFI_ASM + +#include +#include + +/* LONG_LONG_MAX is not always defined (not if STRICT_ANSI, for example). + But we can find it either under the correct ANSI name, or under GNU + C's internal name. */ +#ifdef LONG_LONG_MAX +# define FFI_LONG_LONG_MAX LONG_LONG_MAX +#else +# ifdef LLONG_MAX +# define FFI_LONG_LONG_MAX LLONG_MAX +# else +# ifdef __GNUC__ +# define FFI_LONG_LONG_MAX __LONG_LONG_MAX__ +# endif +# ifdef _MSC_VER +# define FFI_LONG_LONG_MAX _I64_MAX +# endif +# endif +#endif + +#if SCHAR_MAX == 127 +# define ffi_type_uchar ffi_type_uint8 +# define ffi_type_schar ffi_type_sint8 +#else + #error "char size not supported" +#endif + +#if SHRT_MAX == 32767 +# define ffi_type_ushort ffi_type_uint16 +# define ffi_type_sshort ffi_type_sint16 +#elif SHRT_MAX == 2147483647 +# define ffi_type_ushort ffi_type_uint32 +# define ffi_type_sshort ffi_type_sint32 +#else + #error "short size not supported" +#endif + +#if INT_MAX == 32767 +# define ffi_type_uint ffi_type_uint16 +# define ffi_type_sint ffi_type_sint16 +#elif INT_MAX == 2147483647 +# define ffi_type_uint ffi_type_uint32 +# define ffi_type_sint ffi_type_sint32 +#elif INT_MAX == 9223372036854775807 +# define ffi_type_uint ffi_type_uint64 +# define ffi_type_sint ffi_type_sint64 +#else + #error "int size not supported" +#endif + +#define ffi_type_ulong ffi_type_uint64 +#define ffi_type_slong ffi_type_sint64 +#if LONG_MAX == 2147483647 +# if FFI_LONG_LONG_MAX != 9223372036854775807 + #error "no 64-bit data type supported" +# endif +#elif LONG_MAX != 9223372036854775807 + #error "long size not supported" +#endif + +/* The closure code assumes that this works on pointers, i.e. a size_t */ +/* can hold a pointer. */ + +typedef struct _ffi_type +{ + size_t size; + unsigned short alignment; + unsigned short type; + /*@null@*/ struct _ffi_type **elements; +} ffi_type; + +/* These are defined in types.c */ +extern ffi_type ffi_type_void; +extern ffi_type ffi_type_uint8; +extern ffi_type ffi_type_sint8; +extern ffi_type ffi_type_uint16; +extern ffi_type ffi_type_sint16; +extern ffi_type ffi_type_uint32; +extern ffi_type ffi_type_sint32; +extern ffi_type ffi_type_uint64; +extern ffi_type ffi_type_sint64; +extern ffi_type ffi_type_float; +extern ffi_type ffi_type_double; +extern ffi_type ffi_type_longdouble; +extern ffi_type ffi_type_pointer; + + +typedef enum { + FFI_OK = 0, + FFI_BAD_TYPEDEF, + FFI_BAD_ABI +} ffi_status; + +typedef unsigned FFI_TYPE; + +typedef struct { + ffi_abi abi; + unsigned nargs; + /*@dependent@*/ ffi_type **arg_types; + /*@dependent@*/ ffi_type *rtype; + unsigned bytes; + unsigned flags; +#ifdef FFI_EXTRA_CIF_FIELDS + FFI_EXTRA_CIF_FIELDS; +#endif +} ffi_cif; + +/* ---- Definitions for the raw API -------------------------------------- */ + +#ifdef _WIN64 +#define FFI_SIZEOF_ARG 8 +#else +#define FFI_SIZEOF_ARG 4 +#endif + +typedef union { + ffi_sarg sint; + ffi_arg uint; + float flt; + char data[FFI_SIZEOF_ARG]; + void* ptr; +} ffi_raw; + +void ffi_raw_call (/*@dependent@*/ ffi_cif *cif, + void (*fn)(), + /*@out@*/ void *rvalue, + /*@dependent@*/ ffi_raw *avalue); + +void ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw); +void ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args); +size_t ffi_raw_size (ffi_cif *cif); + +/* This is analogous to the raw API, except it uses Java parameter */ +/* packing, even on 64-bit machines. I.e. on 64-bit machines */ +/* longs and doubles are followed by an empty 64-bit word. */ + +void ffi_java_raw_call (/*@dependent@*/ ffi_cif *cif, + void (*fn)(), + /*@out@*/ void *rvalue, + /*@dependent@*/ ffi_raw *avalue); + +void ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw); +void ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args); +size_t ffi_java_raw_size (ffi_cif *cif); + +/* ---- Definitions for closures ----------------------------------------- */ + +#if FFI_CLOSURES + +typedef struct { + char tramp[FFI_TRAMPOLINE_SIZE]; + ffi_cif *cif; + void (*fun)(ffi_cif*,void*,void**,void*); + void *user_data; +} ffi_closure; + +ffi_status +ffi_prep_closure (ffi_closure*, + ffi_cif *, + void (*fun)(ffi_cif*,void*,void**,void*), + void *user_data); + +typedef struct { + char tramp[FFI_TRAMPOLINE_SIZE]; + + ffi_cif *cif; + +#if !FFI_NATIVE_RAW_API + + /* if this is enabled, then a raw closure has the same layout + as a regular closure. We use this to install an intermediate + handler to do the transaltion, void** -> ffi_raw*. */ + + void (*translate_args)(ffi_cif*,void*,void**,void*); + void *this_closure; + +#endif + + void (*fun)(ffi_cif*,void*,ffi_raw*,void*); + void *user_data; + +} ffi_raw_closure; + +ffi_status +ffi_prep_raw_closure (ffi_raw_closure*, + ffi_cif *cif, + void (*fun)(ffi_cif*,void*,ffi_raw*,void*), + void *user_data); + +ffi_status +ffi_prep_java_raw_closure (ffi_raw_closure*, + ffi_cif *cif, + void (*fun)(ffi_cif*,void*,ffi_raw*,void*), + void *user_data); + +#endif /* FFI_CLOSURES */ + +/* ---- Public interface definition -------------------------------------- */ + +ffi_status ffi_prep_cif(/*@out@*/ /*@partial@*/ ffi_cif *cif, + ffi_abi abi, + unsigned int nargs, + /*@dependent@*/ /*@out@*/ /*@partial@*/ ffi_type *rtype, + /*@dependent@*/ ffi_type **atypes); + +int +ffi_call(/*@dependent@*/ ffi_cif *cif, + void (*fn)(), + /*@out@*/ void *rvalue, + /*@dependent@*/ void **avalue); + +/* Useful for eliminating compiler warnings */ +#define FFI_FN(f) ((void (*)())f) + +/* ---- Definitions shared with assembly code ---------------------------- */ + +#endif + +/* If these change, update src/mips/ffitarget.h. */ +#define FFI_TYPE_VOID 0 +#define FFI_TYPE_INT 1 +#define FFI_TYPE_FLOAT 2 +#define FFI_TYPE_DOUBLE 3 +#if 1 +#define FFI_TYPE_LONGDOUBLE 4 +#else +#define FFI_TYPE_LONGDOUBLE FFI_TYPE_DOUBLE +#endif +#define FFI_TYPE_UINT8 5 +#define FFI_TYPE_SINT8 6 +#define FFI_TYPE_UINT16 7 +#define FFI_TYPE_SINT16 8 +#define FFI_TYPE_UINT32 9 +#define FFI_TYPE_SINT32 10 +#define FFI_TYPE_UINT64 11 +#define FFI_TYPE_SINT64 12 +#define FFI_TYPE_STRUCT 13 +#define FFI_TYPE_POINTER 14 + +/* This should always refer to the last type code (for sanity checks) */ +#define FFI_TYPE_LAST FFI_TYPE_POINTER + +#ifdef __cplusplus +} +#endif + +#endif + Added: pypy/dist/pypy/translator/c/src/libffi_msvc/ffi_common.h ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/c/src/libffi_msvc/ffi_common.h Thu May 15 11:33:19 2008 @@ -0,0 +1,77 @@ +/* ----------------------------------------------------------------------- + ffi_common.h - Copyright (c) 1996 Red Hat, Inc. + + Common internal definitions and macros. Only necessary for building + libffi. + ----------------------------------------------------------------------- */ + +#ifndef FFI_COMMON_H +#define FFI_COMMON_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +/* Check for the existence of memcpy. */ +#if STDC_HEADERS +# include +#else +# ifndef HAVE_MEMCPY +# define memcpy(d, s, n) bcopy ((s), (d), (n)) +# endif +#endif + +#if defined(FFI_DEBUG) +#include +#endif + +#ifdef FFI_DEBUG +/*@exits@*/ void ffi_assert(/*@temp@*/ char *expr, /*@temp@*/ char *file, int line); +void ffi_stop_here(void); +void ffi_type_test(/*@temp@*/ /*@out@*/ ffi_type *a, /*@temp@*/ char *file, int line); + +#define FFI_ASSERT(x) ((x) ? (void)0 : ffi_assert(#x, __FILE__,__LINE__)) +#define FFI_ASSERT_AT(x, f, l) ((x) ? 0 : ffi_assert(#x, (f), (l))) +#define FFI_ASSERT_VALID_TYPE(x) ffi_type_test (x, __FILE__, __LINE__) +#else +#define FFI_ASSERT(x) +#define FFI_ASSERT_AT(x, f, l) +#define FFI_ASSERT_VALID_TYPE(x) +#endif + +#define ALIGN(v, a) (((((size_t) (v))-1) | ((a)-1))+1) + +/* Perform machine dependent cif processing */ +ffi_status ffi_prep_cif_machdep(ffi_cif *cif); + +/* Extended cif, used in callback from assembly routine */ +typedef struct +{ + /*@dependent@*/ ffi_cif *cif; + /*@dependent@*/ void *rvalue; + /*@dependent@*/ void **avalue; +} extended_cif; + +/* Terse sized type definitions. */ +typedef unsigned int UINT8 __attribute__((__mode__(__QI__))); +typedef signed int SINT8 __attribute__((__mode__(__QI__))); +typedef unsigned int UINT16 __attribute__((__mode__(__HI__))); +typedef signed int SINT16 __attribute__((__mode__(__HI__))); +typedef unsigned int UINT32 __attribute__((__mode__(__SI__))); +typedef signed int SINT32 __attribute__((__mode__(__SI__))); +typedef unsigned int UINT64 __attribute__((__mode__(__DI__))); +typedef signed int SINT64 __attribute__((__mode__(__DI__))); + +typedef float FLOAT32; + + +#ifdef __cplusplus +} +#endif + +#endif + + Added: pypy/dist/pypy/translator/c/src/libffi_msvc/fficonfig.h ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/c/src/libffi_msvc/fficonfig.h Thu May 15 11:33:19 2008 @@ -0,0 +1,96 @@ +/* fficonfig.h. Originally created by configure, now hand_maintained for MSVC. */ + +/* fficonfig.h. Generated automatically by configure. */ +/* fficonfig.h.in. Generated automatically from configure.in by autoheader. */ + +/* Define this for MSVC, but not for mingw32! */ +#ifdef _MSC_VER +#define __attribute__(x) /* */ +#endif +#define alloca _alloca + +/*----------------------------------------------------------------*/ + +/* Define if using alloca.c. */ +/* #undef C_ALLOCA */ + +/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems. + This function is required for alloca.c support on those systems. */ +/* #undef CRAY_STACKSEG_END */ + +/* Define if you have alloca, as a function or macro. */ +#define HAVE_ALLOCA 1 + +/* Define if you have and it should be used (not on Ultrix). */ +/* #define HAVE_ALLOCA_H 1 */ + +/* If using the C implementation of alloca, define if you know the + direction of stack growth for your system; otherwise it will be + automatically deduced at run-time. + STACK_DIRECTION > 0 => grows toward higher addresses + STACK_DIRECTION < 0 => grows toward lower addresses + STACK_DIRECTION = 0 => direction of growth unknown + */ +/* #undef STACK_DIRECTION */ + +/* Define if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define if you have the memcpy function. */ +#define HAVE_MEMCPY 1 + +/* Define if read-only mmap of a plain file works. */ +//#define HAVE_MMAP_FILE 1 + +/* Define if mmap of /dev/zero works. */ +//#define HAVE_MMAP_DEV_ZERO 1 + +/* Define if mmap with MAP_ANON(YMOUS) works. */ +//#define HAVE_MMAP_ANON 1 + +/* The number of bytes in type double */ +#define SIZEOF_DOUBLE 8 + +/* The number of bytes in type long double */ +#define SIZEOF_LONG_DOUBLE 12 + +/* Define if you have the long double type and it is bigger than a double */ +#define HAVE_LONG_DOUBLE 1 + +/* whether byteorder is bigendian */ +/* #undef WORDS_BIGENDIAN */ + +/* Define if the host machine stores words of multi-word integers in + big-endian order. */ +/* #undef HOST_WORDS_BIG_ENDIAN */ + +/* 1234 = LIL_ENDIAN, 4321 = BIGENDIAN */ +#define BYTEORDER 1234 + +/* Define if your assembler and linker support unaligned PC relative relocs. */ +/* #undef HAVE_AS_SPARC_UA_PCREL */ + +/* Define if your assembler supports .register. */ +/* #undef HAVE_AS_REGISTER_PSEUDO_OP */ + +/* Define if .eh_frame sections should be read-only. */ +/* #undef HAVE_RO_EH_FRAME */ + +/* Define to the flags needed for the .section .eh_frame directive. */ +/* #define EH_FRAME_FLAGS "aw" */ + +/* Define to the flags needed for the .section .eh_frame directive. */ +/* #define EH_FRAME_FLAGS "aw" */ + +/* Define this if you want extra debugging. */ +/* #undef FFI_DEBUG */ + +/* Define this is you do not want support for aggregate types. */ +/* #undef FFI_NO_STRUCTS */ + +/* Define this is you do not want support for the raw API. */ +/* #undef FFI_NO_RAW_API */ + +/* Define this if you are using Purify and want to suppress spurious messages. */ +/* #undef USING_PURIFY */ + Added: pypy/dist/pypy/translator/c/src/libffi_msvc/ffitarget.h ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/c/src/libffi_msvc/ffitarget.h Thu May 15 11:33:19 2008 @@ -0,0 +1,85 @@ +/* -----------------------------------------------------------------*-C-*- + ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc. + Target configuration macros for x86 and x86-64. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + ``Software''), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR + OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. + + ----------------------------------------------------------------------- */ + +#ifndef LIBFFI_TARGET_H +#define LIBFFI_TARGET_H + +/* ---- System specific configurations ----------------------------------- */ + +#if defined (X86_64) && defined (__i386__) +#undef X86_64 +#define X86 +#endif + +/* ---- Generic type definitions ----------------------------------------- */ + +#ifndef LIBFFI_ASM +#ifndef _WIN64 +typedef unsigned long ffi_arg; +#else +typedef unsigned __int64 ffi_arg; +#endif +typedef signed long ffi_sarg; + +typedef enum ffi_abi { + FFI_FIRST_ABI = 0, + + /* ---- Intel x86 Win32 ---------- */ + FFI_SYSV, +#ifndef _WIN64 + FFI_STDCALL, +#endif + /* TODO: Add fastcall support for the sake of completeness */ + FFI_DEFAULT_ABI = FFI_SYSV, + + /* ---- Intel x86 and AMD x86-64 - */ +/* #if !defined(X86_WIN32) && (defined(__i386__) || defined(__x86_64__)) */ +/* FFI_SYSV, */ +/* FFI_UNIX64,*/ /* Unix variants all use the same ABI for x86-64 */ +/* #ifdef __i386__ */ +/* FFI_DEFAULT_ABI = FFI_SYSV, */ +/* #else */ +/* FFI_DEFAULT_ABI = FFI_UNIX64, */ +/* #endif */ +/* #endif */ + + FFI_LAST_ABI = FFI_DEFAULT_ABI + 1 +} ffi_abi; +#endif + +/* ---- Definitions for closures ----------------------------------------- */ + +#define FFI_CLOSURES 1 + +#ifdef _WIN64 +#define FFI_TRAMPOLINE_SIZE 29 +#define FFI_NATIVE_RAW_API 0 +#else +#define FFI_TRAMPOLINE_SIZE 15 +#define FFI_NATIVE_RAW_API 1 /* x86 has native raw api support */ +#endif + +#endif + Added: pypy/dist/pypy/translator/c/src/libffi_msvc/prep_cif.c ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/c/src/libffi_msvc/prep_cif.c Thu May 15 11:33:19 2008 @@ -0,0 +1,175 @@ +/* ----------------------------------------------------------------------- + prep_cif.c - Copyright (c) 1996, 1998 Red Hat, Inc. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + ``Software''), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR + OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. + ----------------------------------------------------------------------- */ + +#include +#include +#include + + +/* Round up to FFI_SIZEOF_ARG. */ + +#define STACK_ARG_SIZE(x) ALIGN(x, FFI_SIZEOF_ARG) + +/* Perform machine independent initialization of aggregate type + specifications. */ + +static ffi_status initialize_aggregate(/*@out@*/ ffi_type *arg) +{ + ffi_type **ptr; + + FFI_ASSERT(arg != NULL); + + /*@-usedef@*/ + + FFI_ASSERT(arg->elements != NULL); + FFI_ASSERT(arg->size == 0); + FFI_ASSERT(arg->alignment == 0); + + ptr = &(arg->elements[0]); + + while ((*ptr) != NULL) + { + if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK)) + return FFI_BAD_TYPEDEF; + + /* Perform a sanity check on the argument type */ + FFI_ASSERT_VALID_TYPE(*ptr); + + arg->size = ALIGN(arg->size, (*ptr)->alignment); + arg->size += (*ptr)->size; + + arg->alignment = (arg->alignment > (*ptr)->alignment) ? + arg->alignment : (*ptr)->alignment; + + ptr++; + } + + /* Structure size includes tail padding. This is important for + structures that fit in one register on ABIs like the PowerPC64 + Linux ABI that right justify small structs in a register. + It's also needed for nested structure layout, for example + struct A { long a; char b; }; struct B { struct A x; char y; }; + should find y at an offset of 2*sizeof(long) and result in a + total size of 3*sizeof(long). */ + arg->size = ALIGN (arg->size, arg->alignment); + + if (arg->size == 0) + return FFI_BAD_TYPEDEF; + else + return FFI_OK; + + /*@=usedef@*/ +} + +/* Perform machine independent ffi_cif preparation, then call + machine dependent routine. */ + +ffi_status ffi_prep_cif(/*@out@*/ /*@partial@*/ ffi_cif *cif, + ffi_abi abi, unsigned int nargs, + /*@dependent@*/ /*@out@*/ /*@partial@*/ ffi_type *rtype, + /*@dependent@*/ ffi_type **atypes) +{ + unsigned bytes = 0; + unsigned int i; + ffi_type **ptr; + + FFI_ASSERT(cif != NULL); + FFI_ASSERT((abi > FFI_FIRST_ABI) && (abi <= FFI_DEFAULT_ABI)); + + cif->abi = abi; + cif->arg_types = atypes; + cif->nargs = nargs; + cif->rtype = rtype; + + cif->flags = 0; + + /* Initialize the return type if necessary */ + /*@-usedef@*/ + if ((cif->rtype->size == 0) && (initialize_aggregate(cif->rtype) != FFI_OK)) + return FFI_BAD_TYPEDEF; + /*@=usedef@*/ + + /* Perform a sanity check on the return type */ + FFI_ASSERT_VALID_TYPE(cif->rtype); + + /* x86-64 and s390 stack space allocation is handled in prep_machdep. */ +#if !defined M68K && !defined __x86_64__ && !defined S390 + /* Make space for the return structure pointer */ + if (cif->rtype->type == FFI_TYPE_STRUCT + /* MSVC returns small structures in registers. But we have a different + workaround: pretend int32 or int64 return type, and converting to + structure afterwards. */ +#ifdef SPARC + && (cif->abi != FFI_V9 || cif->rtype->size > 32) +#endif + ) + bytes = STACK_ARG_SIZE(sizeof(void*)); +#endif + + for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++) + { + + /* Initialize any uninitialized aggregate type definitions */ + if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK)) + return FFI_BAD_TYPEDEF; + + /* Perform a sanity check on the argument type, do this + check after the initialization. */ + FFI_ASSERT_VALID_TYPE(*ptr); + +#if !defined __x86_64__ && !defined S390 +#ifdef SPARC + if (((*ptr)->type == FFI_TYPE_STRUCT + && ((*ptr)->size > 16 || cif->abi != FFI_V9)) + || ((*ptr)->type == FFI_TYPE_LONGDOUBLE + && cif->abi != FFI_V9)) + bytes += sizeof(void*); + else +#endif + { +#if !defined(_MSC_VER) && !defined(__MINGW32__) + /* Don't know if this is a libffi bug or not. At least on + Windows with MSVC, function call parameters are *not* + aligned in the same way as structure fields are, they are + only aligned in integer boundaries. + + This doesn't do any harm for cdecl functions and closures, + since the caller cleans up the stack, but it is wrong for + stdcall functions where the callee cleans. + */ + + /* Add any padding if necessary */ + if (((*ptr)->alignment - 1) & bytes) + bytes = ALIGN(bytes, (*ptr)->alignment); + +#endif + bytes += STACK_ARG_SIZE((*ptr)->size); + } +#endif + } + + cif->bytes = bytes; + + /* Perform machine dependent cif processing */ + return ffi_prep_cif_machdep(cif); +} Added: pypy/dist/pypy/translator/c/src/libffi_msvc/pypy_ffi.c ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/c/src/libffi_msvc/pypy_ffi.c Thu May 15 11:33:19 2008 @@ -0,0 +1,43 @@ +/* This file contains definition from symbols not defined + * in the libffi_msvc directory of CPython. + * most definitions wer copied from the ctypes.c file. + */ + +#include "ffi.h" +#include +#include + +typedef struct { char c; long long x; } s_long_long; +typedef struct { char c; float x; } s_float; +typedef struct { char c; double x; } s_double; +typedef struct { char c; void *x; } s_void_p; +#define FLOAT_ALIGN (sizeof(s_float) - sizeof(float)) +#define DOUBLE_ALIGN (sizeof(s_double) - sizeof(double)) +#define LONG_LONG_ALIGN (sizeof(s_long_long) - sizeof(long long)) +#define VOID_P_ALIGN (sizeof(s_void_p) - sizeof(void*)) + +/* align and size are bogus for void, but they must not be zero */ +ffi_type ffi_type_void = { 1, 1, FFI_TYPE_VOID }; + +ffi_type ffi_type_uint8 = { 1, 1, FFI_TYPE_UINT8 }; +ffi_type ffi_type_sint8 = { 1, 1, FFI_TYPE_SINT8 }; + +ffi_type ffi_type_uint16 = { 2, 2, FFI_TYPE_UINT16 }; +ffi_type ffi_type_sint16 = { 2, 2, FFI_TYPE_SINT16 }; + +ffi_type ffi_type_uint32 = { 4, 4, FFI_TYPE_UINT32 }; +ffi_type ffi_type_sint32 = { 4, 4, FFI_TYPE_SINT32 }; + +ffi_type ffi_type_uint64 = { 8, LONG_LONG_ALIGN, FFI_TYPE_UINT64 }; +ffi_type ffi_type_sint64 = { 8, LONG_LONG_ALIGN, FFI_TYPE_SINT64 }; + +ffi_type ffi_type_float = { sizeof(float), FLOAT_ALIGN, FFI_TYPE_FLOAT }; +ffi_type ffi_type_double = { sizeof(double), DOUBLE_ALIGN, FFI_TYPE_DOUBLE }; + +ffi_type ffi_type_pointer = { sizeof(void *), VOID_P_ALIGN, FFI_TYPE_POINTER }; + +void ffi_fatalerror(const char* msg) { + fprintf(stderr, "%s\\n", msg); + abort(); +} + Added: pypy/dist/pypy/translator/c/src/libffi_msvc/types.c ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/c/src/libffi_msvc/types.c Thu May 15 11:33:19 2008 @@ -0,0 +1,104 @@ +/* ----------------------------------------------------------------------- + types.c - Copyright (c) 1996, 1998 Red Hat, Inc. + + Predefined ffi_types needed by libffi. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + ``Software''), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR + OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. + ----------------------------------------------------------------------- */ + +#include +#include + +/* Type definitions */ + +#define FFI_INTEGRAL_TYPEDEF(n, s, a, t) ffi_type ffi_type_##n = { s, a, t, NULL } +#define FFI_AGGREGATE_TYPEDEF(n, e) ffi_type ffi_type_##n = { 0, 0, FFI_TYPE_STRUCT, e } + +/* Size and alignment are fake here. They must not be 0. */ +FFI_INTEGRAL_TYPEDEF(void, 1, 1, FFI_TYPE_VOID); + +FFI_INTEGRAL_TYPEDEF(uint8, 1, 1, FFI_TYPE_UINT8); +FFI_INTEGRAL_TYPEDEF(sint8, 1, 1, FFI_TYPE_SINT8); +FFI_INTEGRAL_TYPEDEF(uint16, 2, 2, FFI_TYPE_UINT16); +FFI_INTEGRAL_TYPEDEF(sint16, 2, 2, FFI_TYPE_SINT16); +FFI_INTEGRAL_TYPEDEF(uint32, 4, 4, FFI_TYPE_UINT32); +FFI_INTEGRAL_TYPEDEF(sint32, 4, 4, FFI_TYPE_SINT32); +FFI_INTEGRAL_TYPEDEF(float, 4, 4, FFI_TYPE_FLOAT); + +#if defined ALPHA || defined SPARC64 || defined X86_64 || defined S390X \ + || defined IA64 + +FFI_INTEGRAL_TYPEDEF(pointer, 8, 8, FFI_TYPE_POINTER); + +#else + +FFI_INTEGRAL_TYPEDEF(pointer, 4, 4, FFI_TYPE_POINTER); + +#endif + +#if defined X86 || defined X86_WIN32 || defined ARM || defined M68K + +FFI_INTEGRAL_TYPEDEF(uint64, 8, 4, FFI_TYPE_UINT64); +FFI_INTEGRAL_TYPEDEF(sint64, 8, 4, FFI_TYPE_SINT64); + +#elif defined SH + +FFI_INTEGRAL_TYPEDEF(uint64, 8, 4, FFI_TYPE_UINT64); +FFI_INTEGRAL_TYPEDEF(sint64, 8, 4, FFI_TYPE_SINT64); + +#else + +FFI_INTEGRAL_TYPEDEF(uint64, 8, 8, FFI_TYPE_UINT64); +FFI_INTEGRAL_TYPEDEF(sint64, 8, 8, FFI_TYPE_SINT64); + +#endif + + +#if defined X86 || defined X86_WIN32 || defined M68K + +FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE); +FFI_INTEGRAL_TYPEDEF(longdouble, 12, 4, FFI_TYPE_LONGDOUBLE); + +#elif defined ARM || defined SH || defined POWERPC_AIX || defined POWERPC_DARWIN + +FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE); +FFI_INTEGRAL_TYPEDEF(longdouble, 8, 4, FFI_TYPE_LONGDOUBLE); + +#elif defined SPARC + +FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE); +#ifdef SPARC64 +FFI_INTEGRAL_TYPEDEF(longdouble, 16, 16, FFI_TYPE_LONGDOUBLE); +#else +FFI_INTEGRAL_TYPEDEF(longdouble, 16, 8, FFI_TYPE_LONGDOUBLE); +#endif + +#elif defined X86_64 + +FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE); +FFI_INTEGRAL_TYPEDEF(longdouble, 16, 16, FFI_TYPE_LONGDOUBLE); + +#else + +FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE); +FFI_INTEGRAL_TYPEDEF(longdouble, 8, 8, FFI_TYPE_LONGDOUBLE); + +#endif + Added: pypy/dist/pypy/translator/c/src/libffi_msvc/win32.c ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/c/src/libffi_msvc/win32.c Thu May 15 11:33:19 2008 @@ -0,0 +1,267 @@ +/* ----------------------------------------------------------------------- + win32.S - Copyright (c) 1996, 1998, 2001, 2002 Red Hat, Inc. + Copyright (c) 2001 John Beniton + Copyright (c) 2002 Ranjit Mathew + + + X86 Foreign Function Interface + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + ``Software''), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR + OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. + ----------------------------------------------------------------------- */ + +/* theller: almost verbatim translation from gas syntax to MSVC inline + assembler code. */ + +/* theller: ffi_call_SYSV and ffi_call_STDCALL now return an integer - the + difference of the stack pointer before and after the function call. If + everything is ok, zero is returned. If stdcall functions are passed the + wrong number of arguments, the difference will be nonzero. */ + +#include +#include + +__declspec(naked) int +ffi_call_SYSV(void (* prepfunc)(char *, extended_cif *), /* 8 */ + extended_cif *ecif, /* 12 */ + unsigned bytes, /* 16 */ + unsigned flags, /* 20 */ + unsigned *rvalue, /* 24 */ + void (*fn)()) /* 28 */ +{ + _asm { + push ebp + mov ebp, esp + + push esi // NEW: this register must be preserved across function calls +// XXX SAVE ESP NOW! + mov esi, esp // save stack pointer before the call + +// Make room for all of the new args. + mov ecx, [ebp+16] + sub esp, ecx // sub esp, bytes + + mov eax, esp + +// Place all of the ffi_prep_args in position + push [ebp + 12] // ecif + push eax + call [ebp + 8] // prepfunc + +// Return stack to previous state and call the function + add esp, 8 +// FIXME: Align the stack to a 128-bit boundary to avoid +// potential performance hits. + call [ebp + 28] +// Remove the space we pushed for the args + mov ecx, [ebp + 16] + add esp, ecx + +// XXX ASSERT THAT ESP IS THE SAME NOW THAN BEFORE! + sub esi, esp + +// Load %ecx with the return type code + mov ecx, [ebp + 20] + +// If the return value pointer is NULL, assume no return value. +/* + Intel asm is weird. We have to explicitely specify 'DWORD PTR' in the nexr instruction, + otherwise only one BYTE will be compared (instead of a DWORD)! + */ + cmp DWORD PTR [ebp + 24], 0 + jne sc_retint + +// Even if there is no space for the return value, we are +// obliged to handle floating-point values. + cmp ecx, FFI_TYPE_FLOAT + jne sc_noretval +// fstp %st(0) + fstp st(0) + + jmp sc_epilogue + +sc_retint: + cmp ecx, FFI_TYPE_INT + jne sc_retfloat +// # Load %ecx with the pointer to storage for the return value + mov ecx, [ebp + 24] + mov [ecx + 0], eax + jmp sc_epilogue + +sc_retfloat: + cmp ecx, FFI_TYPE_FLOAT + jne sc_retdouble +// Load %ecx with the pointer to storage for the return value + mov ecx, [ebp+24] +// fstps (%ecx) + fstp DWORD PTR [ecx] + jmp sc_epilogue + +sc_retdouble: + cmp ecx, FFI_TYPE_DOUBLE + jne sc_retlongdouble +// movl 24(%ebp),%ecx + mov ecx, [ebp+24] + fstp QWORD PTR [ecx] + jmp sc_epilogue + + jmp sc_retlongdouble // avoid warning about unused label +sc_retlongdouble: + cmp ecx, FFI_TYPE_LONGDOUBLE + jne sc_retint64 +// Load %ecx with the pointer to storage for the return value + mov ecx, [ebp+24] +// fstpt (%ecx) + fstp QWORD PTR [ecx] /* XXX ??? */ + jmp sc_epilogue + +sc_retint64: + cmp ecx, FFI_TYPE_SINT64 + jne sc_retstruct +// Load %ecx with the pointer to storage for the return value + mov ecx, [ebp+24] + mov [ecx+0], eax + mov [ecx+4], edx + +sc_retstruct: +// Nothing to do! + +sc_noretval: +sc_epilogue: + mov eax, esi + pop esi // NEW restore: must be preserved across function calls + mov esp, ebp + pop ebp + ret + } +} + +__declspec(naked) int +ffi_call_STDCALL(void (* prepfunc)(char *, extended_cif *), /* 8 */ + extended_cif *ecif, /* 12 */ + unsigned bytes, /* 16 */ + unsigned flags, /* 20 */ + unsigned *rvalue, /* 24 */ + void (*fn)()) /* 28 */ +{ + _asm { + push ebp + mov ebp, esp + + push esi // NEW: this register must be preserved across function calls + +// XXX SAVE ESP NOW! + mov esi, esp + +// Make room for all of the new args. + mov ecx, [ebp+16] + sub esp, ecx + + mov eax, esp + +// Place all of the ffi_prep_args in position + push [ebp + 12] // ecif + push eax + call [ebp + 8] // prepfunc + +// Return stack to previous state and call the function + add esp, 8 +// FIXME: Align the stack to a 128-bit boundary to avoid +// potential performance hits. + call [ebp + 28] +// stdcall functions pop arguments off the stack themselves + +// XXX IS ESP NOW THE SAME AS BEFORE? + sub esi, esp + +// Load %ecx with the return type code + mov ecx, [ebp + 20] + +// If the return value pointer is NULL, assume no return value. +/* + Intel asm is weird. We have to explicitely specify 'DWORD PTR' in the nexr instruction, + otherwise only one BYTE will be compared (instead of a DWORD)! + */ + cmp DWORD PTR [ebp + 24], 0 + jne sc_retint + +// Even if there is no space for the return value, we are +// obliged to handle floating-point values. + cmp ecx, FFI_TYPE_FLOAT + jne sc_noretval +// fstp %st(0) + fstp st(0) + + jmp sc_epilogue + +sc_retint: + cmp ecx, FFI_TYPE_INT + jne sc_retfloat +// # Load %ecx with the pointer to storage for the return value + mov ecx, [ebp + 24] + mov [ecx + 0], eax + jmp sc_epilogue + +sc_retfloat: + cmp ecx, FFI_TYPE_FLOAT + jne sc_retdouble +// Load %ecx with the pointer to storage for the return value + mov ecx, [ebp+24] +// fstps (%ecx) + fstp DWORD PTR [ecx] + jmp sc_epilogue + +sc_retdouble: + cmp ecx, FFI_TYPE_DOUBLE + jne sc_retlongdouble +// movl 24(%ebp),%ecx + mov ecx, [ebp+24] + fstp QWORD PTR [ecx] + jmp sc_epilogue + + jmp sc_retlongdouble // avoid warning about unused label +sc_retlongdouble: + cmp ecx, FFI_TYPE_LONGDOUBLE + jne sc_retint64 +// Load %ecx with the pointer to storage for the return value + mov ecx, [ebp+24] +// fstpt (%ecx) + fstp QWORD PTR [ecx] /* XXX ??? */ + jmp sc_epilogue + +sc_retint64: + cmp ecx, FFI_TYPE_SINT64 + jne sc_retstruct +// Load %ecx with the pointer to storage for the return value + mov ecx, [ebp+24] + mov [ecx+0], eax + mov [ecx+4], edx + +sc_retstruct: +// Nothing to do! + +sc_noretval: +sc_epilogue: + mov eax, esi + pop esi // NEW restore: must be preserved across function calls + mov esp, ebp + pop ebp + ret + } +} From antocuni at codespeak.net Thu May 15 13:55:08 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 15 May 2008 13:55:08 +0200 (CEST) Subject: [pypy-svn] r54748 - in pypy/dist/pypy/translator/tool: . test Message-ID: <20080515115508.E151C2A8007@codespeak.net> Author: antocuni Date: Thu May 15 13:55:06 2008 New Revision: 54748 Modified: pypy/dist/pypy/translator/tool/cbuild.py pypy/dist/pypy/translator/tool/test/test_cbuild.py Log: revert r54745, as it breaks translation on linux Modified: pypy/dist/pypy/translator/tool/cbuild.py ============================================================================== --- pypy/dist/pypy/translator/tool/cbuild.py (original) +++ pypy/dist/pypy/translator/tool/cbuild.py Thu May 15 13:55:06 2008 @@ -317,8 +317,7 @@ cmdobj = build_shared_library(dist) cmdobj.inplace = True cmdobj.force = True - if (sys.platform == 'win32' - and sys.executable.lower().endswith('_d.exe')): + if sys.platform == 'win32' and sys.executable.endswith('_d.exe'): cmdobj.debug = True dist.command_obj["build_ext"] = cmdobj dist.have_run["build_ext"] = 0 @@ -480,10 +479,8 @@ linker_exe linker_so'''.split(): compiler.executables[c][0] = self.compiler_exe compiler.spawn = log_spawned_cmd(compiler.spawn) - self.eci = self.eci.convert_sources_to_files() - filenames = self.cfilenames + list(self.eci.separate_module_files) objects = [] - for cfile in filenames: + for cfile in self.cfilenames: cfile = py.path.local(cfile) old = cfile.dirpath().chdir() try: Modified: pypy/dist/pypy/translator/tool/test/test_cbuild.py ============================================================================== --- pypy/dist/pypy/translator/tool/test/test_cbuild.py (original) +++ pypy/dist/pypy/translator/tool/test/test_cbuild.py Thu May 15 13:55:06 2008 @@ -45,12 +45,9 @@ { printf("%f\\n", pow(2.0, 2.0)); }''') - if sys.platform != 'win32': - eci = ExternalCompilationInfo( - libraries = ['m'], - ) - else: - eci = ExternalCompilationInfo() + eci = ExternalCompilationInfo( + libraries = ['m'], + ) output = build_executable([c_file], eci) p = Popen(output, stdout=PIPE, stderr=STDOUT) p.wait() @@ -112,8 +109,7 @@ int get() { return 42; - }'''], - export_symbols = ['get'] + }'''] ) neweci = eci.compile_shared_lib() assert len(neweci.libraries) == 1 From afa at codespeak.net Thu May 15 19:43:07 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Thu, 15 May 2008 19:43:07 +0200 (CEST) Subject: [pypy-svn] r54758 - pypy/dist/pypy/rpython/tool Message-ID: <20080515174307.725551684C2@codespeak.net> Author: afa Date: Thu May 15 19:43:06 2008 New Revision: 54758 Modified: pypy/dist/pypy/rpython/tool/rffi_platform.py Log: Another attempt for r54745: Ability to use separate_module_files and separate_module_sources as input for rffi_platform.configure. Modified: pypy/dist/pypy/rpython/tool/rffi_platform.py ============================================================================== --- pypy/dist/pypy/rpython/tool/rffi_platform.py (original) +++ pypy/dist/pypy/rpython/tool/rffi_platform.py Thu May 15 19:43:06 2008 @@ -530,7 +530,9 @@ """ def run_example_code(filepath, eci): - output = build_executable_cache([filepath], eci) + eci = eci.convert_sources_to_files() + files = [filepath] + list(eci.separate_module_files) + output = build_executable_cache(files, eci) section = None for line in output.splitlines(): line = line.strip() From afa at codespeak.net Thu May 15 19:48:45 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Thu, 15 May 2008 19:48:45 +0200 (CEST) Subject: [pypy-svn] r54759 - pypy/dist/pypy/rlib/test Message-ID: <20080515174845.057CB1684C4@codespeak.net> Author: afa Date: Thu May 15 19:48:43 2008 New Revision: 54759 Modified: pypy/dist/pypy/rlib/test/test_libffi.py Log: Python2.4 compatibility Modified: pypy/dist/pypy/rlib/test/test_libffi.py ============================================================================== --- pypy/dist/pypy/rlib/test/test_libffi.py (original) +++ pypy/dist/pypy/rlib/test/test_libffi.py Thu May 15 19:48:43 2008 @@ -13,7 +13,8 @@ import time def setup_module(mod): - if not sys.platform.startswith(('linux', 'win32')): + if not (sys.platform.startswith('linux') or + sys.platform == 'win32'): py.test.skip("Fragile tests, linux & win32 only by now") for name in type_names: # XXX force this to be seen by ll2ctypes From pypy-svn at codespeak.net Thu May 15 21:50:12 2008 From: pypy-svn at codespeak.net (VIAGRA ® Official Site) Date: Thu, 15 May 2008 21:50:12 +0200 (CEST) Subject: [pypy-svn] Dear pypy-svn@codespeak.net May 89% 0FF Message-ID: <20080515104832.3577.qmail@aedi46.neoplus.adsl.tpnet.pl> An HTML attachment was scrubbed... URL: From afa at codespeak.net Thu May 15 23:18:41 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Thu, 15 May 2008 23:18:41 +0200 (CEST) Subject: [pypy-svn] r54766 - in pypy/dist/pypy/rlib: . test Message-ID: <20080515211841.A9676168476@codespeak.net> Author: afa Date: Thu May 15 23:18:40 2008 New Revision: 54766 Modified: pypy/dist/pypy/rlib/_rsocket_rffi.py pypy/dist/pypy/rlib/getaddrinfo.py pypy/dist/pypy/rlib/rpoll.py pypy/dist/pypy/rlib/rsocket.py pypy/dist/pypy/rlib/test/test_rpoll.py Log: Various corrections in the win32 implementation of rsocket and rpoll. More tests pass. Modified: pypy/dist/pypy/rlib/_rsocket_rffi.py ============================================================================== --- pypy/dist/pypy/rlib/_rsocket_rffi.py (original) +++ pypy/dist/pypy/rlib/_rsocket_rffi.py Thu May 15 23:18:40 2008 @@ -54,7 +54,8 @@ eci = ExternalCompilationInfo( pre_include_lines = (HEADER + COND_HEADER).split("\n"), - includes = includes + includes = includes, + libraries = libraries, ) class CConfig: Modified: pypy/dist/pypy/rlib/getaddrinfo.py ============================================================================== --- pypy/dist/pypy/rlib/getaddrinfo.py (original) +++ pypy/dist/pypy/rlib/getaddrinfo.py Thu May 15 23:18:40 2008 @@ -228,7 +228,7 @@ for address in address_list: if address.family == _c.AF_INET: a = address.lock(_c.sockaddr_in) - rffi.setintfield(a, 'c_sin_port', port & 0xffff) + rffi.setintfield(a, 'c_sin_port', r_uint(port) & 0xffff) address.unlock() a = address.lock() addr = make_address(a, address.addrlen, address_to_fill) Modified: pypy/dist/pypy/rlib/rpoll.py ============================================================================== --- pypy/dist/pypy/rlib/rpoll.py (original) +++ pypy/dist/pypy/rlib/rpoll.py Thu May 15 23:18:40 2008 @@ -16,10 +16,10 @@ POLLRDNORM POLLRDBAND POLLWRNORM POLLWEBAND POLLMSG'''.split() eventnames = [name for name in eventnames - if getattr(_c.cConfig, name) is not None] + if _c.constants.get(name) is not None] for name in eventnames: - globals()[name] = getattr(_c.cConfig, name) + globals()[name] = _c.constants[name] class PollError(Exception): def __init__(self, errno): @@ -95,7 +95,8 @@ # select socket for desired events event = _c.WSACreateEvent() - _c.WSAEventSelect(fd, event, wsaEvents) + if _c.WSAEventSelect(fd, event, wsaEvents) != 0: + raise PollError(_c.geterrno()) eventdict[fd] = event socketevents[numevents] = event @@ -154,8 +155,9 @@ lltype.free(info, flavor='raw') finally: - for i in range(numevents): - _c.WSACloseEvent(socketevents[i]) + for fd, event in eventdict.iteritems(): + _c.WSAEventSelect(fd, event, 0) + _c.WSACloseEvent(event) lltype.free(socketevents, flavor='raw') return retval Modified: pypy/dist/pypy/rlib/rsocket.py ============================================================================== --- pypy/dist/pypy/rlib/rsocket.py (original) +++ pypy/dist/pypy/rlib/rsocket.py Thu May 15 23:18:40 2008 @@ -791,7 +791,7 @@ def gettimeout(self): """Return the timeout of the socket. A timeout < 0 means that - timeouts are dissabled in the socket.""" + timeouts are disabled in the socket.""" return self.timeout def listen(self, backlog): Modified: pypy/dist/pypy/rlib/test/test_rpoll.py ============================================================================== --- pypy/dist/pypy/rlib/test/test_rpoll.py (original) +++ pypy/dist/pypy/rlib/test/test_rpoll.py Thu May 15 23:18:40 2008 @@ -33,7 +33,8 @@ assert events[0][1] & POLLOUT err = cli.connect_ex(servaddr) - assert err == 0 + # win32 oddity: returns WSAEISCONN when the connection finally succeed. + assert err == 0 or err == 10056 events = poll({servconn.fileno(): POLLIN, cli.fileno(): POLLIN}, timeout=100) From afa at codespeak.net Fri May 16 00:50:16 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 16 May 2008 00:50:16 +0200 (CEST) Subject: [pypy-svn] r54770 - pypy/dist/pypy/module/_rawffi/test Message-ID: <20080515225016.421481684C4@codespeak.net> Author: afa Date: Fri May 16 00:50:13 2008 New Revision: 54770 Modified: pypy/dist/pypy/module/_rawffi/test/test__rawffi.py Log: Almost all _rawffi tests pass on win32! Modified: pypy/dist/pypy/module/_rawffi/test/test__rawffi.py ============================================================================== --- pypy/dist/pypy/module/_rawffi/test/test__rawffi.py (original) +++ pypy/dist/pypy/module/_rawffi/test/test__rawffi.py Fri May 16 00:50:13 2008 @@ -9,8 +9,8 @@ import os, sys, py def setup_module(mod): - if sys.platform != 'linux2': - py.test.skip("Linux only tests by now") + if sys.platform not in ('linux2', 'win32'): + py.test.skip("Linux & win32 only tests by now") class AppTestFfi: def prepare_c_example(): @@ -145,23 +145,44 @@ } ''')) - return compile_c_module([c_file], 'x', ExternalCompilationInfo()) + symbols = """get_char char_check get_raw_pointer + add_shorts + inner_struct_elem create_double_struct free_double_struct + get_array_elem get_array_elem_s + nothing + some_huge_value some_huge_uvalue pass_ll + runcallback + allocate_array + static_int static_double + sum_x_y + give perturb + """.split() + eci = ExternalCompilationInfo(export_symbols=symbols) + return compile_c_module([c_file], 'x', eci) prepare_c_example = staticmethod(prepare_c_example) def setup_class(cls): space = gettestobjspace(usemodules=('_rawffi','struct')) cls.space = space cls.w_lib_name = space.wrap(cls.prepare_c_example()) + if sys.platform == 'win32': + cls.w_iswin32 = space.wrap(True) + cls.w_libc_name = space.wrap('msvcrt') + cls.w_libm_name = space.wrap('msvcrt') + else: + cls.w_iswin32 = space.wrap(False) + cls.w_libc_name = space.wrap('libc.so.6') + cls.w_libm_name = space.wrap('libm.so') cls.w_sizes_and_alignments = space.wrap(dict( [(k, (v.c_size, v.c_alignment)) for k,v in TYPEMAP.iteritems()])) def test_libload(self): import _rawffi - _rawffi.CDLL('libc.so.6') + _rawffi.CDLL(self.libc_name) def test_getattr(self): import _rawffi - libc = _rawffi.CDLL('libc.so.6') + libc = _rawffi.CDLL(self.libc_name) func = libc.ptr('rand', [], 'i') assert libc.ptr('rand', [], 'i') is func # caching assert libc.ptr('rand', [], 'l') is not func @@ -256,7 +277,7 @@ def test_pow(self): import _rawffi - libm = _rawffi.CDLL('libm.so') + libm = _rawffi.CDLL(self.libm_name) pow = libm.ptr('pow', ['d', 'd'], 'd') A = _rawffi.Array('d') arg1 = A(1) @@ -271,7 +292,7 @@ def test_time(self): import _rawffi - libc = _rawffi.CDLL('libc.so.6') + libc = _rawffi.CDLL(self.libc_name) time = libc.ptr('time', ['z'], 'l') # 'z' instead of 'P' just for test arg = _rawffi.Array('P')(1) arg[0] = 0 @@ -280,10 +301,12 @@ arg.free() def test_gettimeofday(self): + if self.iswin32: + skip("No gettimeofday on win32") import _rawffi struct_type = _rawffi.Structure([('tv_sec', 'l'), ('tv_usec', 'l')]) structure = struct_type() - libc = _rawffi.CDLL('libc.so.6') + libc = _rawffi.CDLL(self.libc_name) gettimeofday = libc.ptr('gettimeofday', ['P', 'P'], 'i') arg1 = structure.byptr() @@ -318,7 +341,7 @@ ("tm_wday", 'i'), ("tm_yday", 'i'), ("tm_isdst", 'i')]) - libc = _rawffi.CDLL('libc.so.6') + libc = _rawffi.CDLL(self.libc_name) gmtime = libc.ptr('gmtime', ['P'], 'P') arg = x.byptr() @@ -428,7 +451,7 @@ def test_callback(self): import _rawffi import struct - libc = _rawffi.CDLL('libc.so.6') + libc = _rawffi.CDLL(self.libc_name) ll_to_sort = _rawffi.Array('i')(4) for i in range(4): ll_to_sort[i] = 4-i From afa at codespeak.net Fri May 16 01:34:06 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 16 May 2008 01:34:06 +0200 (CEST) Subject: [pypy-svn] r54771 - pypy/dist/pypy/module/_rawffi/test Message-ID: <20080515233406.C06AC398003@codespeak.net> Author: afa Date: Fri May 16 01:34:05 2008 New Revision: 54771 Modified: pypy/dist/pypy/module/_rawffi/test/test__rawffi.py Log: This test works by pure luck on linux, and fails on win32 which has a different qsort implementation. See how we sort the array by comparing pointers instead of numbers... IMO the callback should be called with all its arguments dereferenced. Modified: pypy/dist/pypy/module/_rawffi/test/test__rawffi.py ============================================================================== --- pypy/dist/pypy/module/_rawffi/test/test__rawffi.py (original) +++ pypy/dist/pypy/module/_rawffi/test/test__rawffi.py Fri May 16 01:34:05 2008 @@ -449,6 +449,7 @@ arg1.free() def test_callback(self): + skip("FIXME: compare actually receives a pair of int**") import _rawffi import struct libc = _rawffi.CDLL(self.libc_name) @@ -457,9 +458,13 @@ ll_to_sort[i] = 4-i qsort = libc.ptr('qsort', ['P', 'i', 'i', 'P'], None) resarray = _rawffi.Array('i')(1) + bogus_args = False def compare(a, b): a1 = _rawffi.Array('i').fromaddress(a, 1) a2 = _rawffi.Array('i').fromaddress(b, 1) + if a1[0] not in [1,2,3,4] or a2[0] not in [1,2,3,4]: + print "comparing", a1[0], "with", a2[0] + bogus_args = True if a1[0] > a2[0]: res = -1 res = 1 @@ -474,6 +479,7 @@ qsort(a1, a2, a3, a4) res = [ll_to_sort[i] for i in range(len(ll_to_sort))] assert res == [1,2,3,4] + assert not bogus_args a1.free() a2.free() a3.free() From cfbolz at codespeak.net Fri May 16 08:55:52 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 16 May 2008 08:55:52 +0200 (CEST) Subject: [pypy-svn] r54772 - pypy/extradoc/talk/s3-2008 Message-ID: <20080516065552.EE9A7168462@codespeak.net> Author: cfbolz Date: Fri May 16 08:55:49 2008 New Revision: 54772 Modified: pypy/extradoc/talk/s3-2008/objmodel.pdf pypy/extradoc/talk/s3-2008/speed.pdf pypy/extradoc/talk/s3-2008/talk.tex Log: accumulated changes Modified: pypy/extradoc/talk/s3-2008/objmodel.pdf ============================================================================== Binary files. No diff available. Modified: pypy/extradoc/talk/s3-2008/speed.pdf ============================================================================== Binary files. No diff available. Modified: pypy/extradoc/talk/s3-2008/talk.tex ============================================================================== --- pypy/extradoc/talk/s3-2008/talk.tex (original) +++ pypy/extradoc/talk/s3-2008/talk.tex Fri May 16 08:55:49 2008 @@ -43,7 +43,7 @@ \and% \vskip-2mm \inst{3}% - ETH Zurich, Switzerland + ETH Z?rich, Switzerland } @@ -81,9 +81,9 @@ \begin{frame} \frametitle{Scope} - This talk is about: XXX + This talk is about: \begin{itemize} - \item writing a Squeak implementation + \item writing a Squeak implementation (called "SPy") in Python \item with eight people \item in five days \item using PyPy @@ -91,14 +91,14 @@ \end{frame} \begin{frame} - \frametitle{What is PyPy} + \frametitle{What is PyPy?} \begin{itemize} \item started as a Python implementation in Python + \item Open Source project, MIT license \item developed into a general environment for implementing dynamic languages \item supports the language developer with a lot of infrastructure - \item Open Source project, MIT license \item most important goal: abstracting over low-level details - \item don't fix decisions about low-level details + \item don't fix decisions about low-level details early \end{itemize} \end{frame} @@ -106,19 +106,18 @@ \frametitle{PyPy's Approach to VM Construction} \begin{itemize} \item implement an interpreter for the dynamic language in RPython - \item translate this interpreter to a low-level language - \item translating inserts low-level details + \item translate this interpreter to a low-level language with PyPy toolchain \item a variety of target environment: C, LLVM, JVM, .NET + %\item translating inserts left-out low-level details % XXX write about model-driven development? \end{itemize} \pause \begin{block} {What is RPython?} \begin{itemize} \item a more static subset of Python - \item static enough to enable type inference - \item still rather expressive: exceptions, inheritance, dynamic dispatch - \item analysis starts after importing of interpreter - \item enables compile-time metaprogramming + \item static enough to allow type inference + \item still rather expressive: exceptions, single inheritance, dynamic dispatch, interesting builtin types, garbage collection + %\item translations starts after importing of interpreter \end{itemize} \end{block} \end{frame} @@ -126,11 +125,12 @@ \begin{frame} \begin{block} {Translation Aspects} \begin{itemize} - \item many aspects of the final VM are orthogonal to language semantics + \item many low-level details of the final VM are orthogonal to language semantics \item examples: GC strategy, threading model, many object details - \item non-trivial translation aspect: auto-generating a dynamic compiler - \item those shouldn't manifest in the interpreter source + \item those shouldn't be visible in the interpreter source \item they are inserted during translation + \pause + \item non-trivial translation aspect: auto-generating a dynamic compiler \end{itemize} \end{block} \pause @@ -147,9 +147,9 @@ \frametitle{The SPy VM} \begin{itemize} \item really simple, straight-forward Squeak interpreter in RPython - \item essentially free of low-level details, no GC - \item written in the course of five days - \item sprint-driven development + \item goal is to fully support loading and running Squeak images + \item source code essentially free of low-level details, no GC + \item written during a five-day sprint in October in Bern \end{itemize} \pause \begin{block} {Status} @@ -162,9 +162,9 @@ \end{block} \end{frame} -\begin{frame} +\begin{frame}[plain] \frametitle{SPy Object Model} - \includegraphics[height=5cm]{objmodel} + \includegraphics[height=7.5cm]{objmodel} \end{frame} \begin{frame} @@ -173,16 +173,17 @@ \begin{itemize} \item classes are just objects: can't really say which objects are used as classes \item any object with the right instance fields can be used as a class - \item cryptic bitfields in the class which the VM needs to decode all the time + \item cryptic (bit)fields in the class which the VM needs to decode all the time \end{itemize} \pause - \begin{block}{Shadows} + \begin{block}{Approach} \begin{itemize} - \item approach: potentially attach a \emph{shadow} to every object + \item potentially attach a \emph{shadow} to every object \item the shadow caches VM-internal information \item when the object is changed, the shadow is invalidated - \item so far only used for classes, later contexts, methods + \item so far only used for classes, probably more later \item conceptual cleanliness and nicer VM implementation + \item still allows to expose low-level view to user code \end{itemize} \end{block} \end{frame} @@ -190,17 +191,18 @@ \begin{frame} \frametitle{Tagged Pointers} \begin{itemize} - \item Squeak implements integers as tagged pointers + \item Squeak implements small integers as tagged pointers \item doing that is orthogonal to language semantics \item in PyPy implemented as a translation aspect - \item one class with exactly one int field can be implemented with a flag + \item one class with exactly one int field can optionally be implemented + with tagged pointers \item when enabled, all method calls check for tag first - \item usually changing such a decision would be a major effort + \item usually changing such an implementation choice would be a major effort \end{itemize} \pause - \begin{block}{Results} + \begin{block}{Results of Tagging} \begin{itemize} - \item small slowdown + \item small slowdown due to need to check for flag \item memory advantage not measured \item really easy to do \end{itemize} @@ -214,7 +216,7 @@ \item failure signaled by an exception \item automatic popping from the stack and unwrapping of arguments \item automatic pushing of the result - \item using a custom decorator \texttt{expose\_primitive} + \item using a custom function decorator \texttt{expose\_primitive} \item compile-time metaprogramming \end{itemize} \end{frame} @@ -231,31 +233,34 @@ ] -def make_func(code, op): +def make_primitive(prim_num, op): - @expose_primitive(code, unwrap_spec=[int, int]) - def func(interp, v1, v2): + @expose_primitive(prim_num, unwrap_spec=[int, int]) + def primitive(interp, v1, v2): res = op(v1, v2) w_res = utility.wrap_bool(res) return w_res -for (code, op) in bool_ops: - make_func(code, op) +for (prim_num, op) in bool_ops: + make_primitive(prim_num, op) \end{verbatim} } -\begin{frame} - \frametitle{Image Loading} - \begin{itemize} - \item manual decoding of Squeak images by reading Squeak object format - \item image writing could be done in the same way later - \item not really a reason to directly use a memory dump - \item (hard anyway, on object-oriented platforms) - \end{itemize} -\end{frame} + +%\begin{frame} +% \frametitle{Image Loading} +% \begin{itemize} +% \item manual decoding of Squeak images by reading Squeak object format +% \item image writing could be done in the same way later +% \item not really possible to directly use a memory dump +% \item not really necessary either +% \item (hard anyway, on object-oriented platforms) +% \end{itemize} +%\end{frame} \frame[plain]{ \frametitle{Performance (tiny Benchmark)} + \centering \includegraphics[height=8cm]{speed} } @@ -272,10 +277,16 @@ {\bf Bad Points of the Approach:} \begin{itemize} \item not really fast (yet) - \item XXX XXX + \item RPython isn't Python + \item toolchain needs quite some effort (but only once) \end{itemize} \end{frame} +% we could mention that we have many abstraction layers and levels in the translation toolchain, +% which is generally good and useful but makes things more complex +% that would be how I'd compare with cola +% of course the question "how do you compare with cola" will be asked, so we need to be ready for it + \begin{frame} \frametitle{Outlook} \begin{itemize} @@ -285,6 +296,12 @@ \item JIT (see next slide) \item lessons learned for a "SqueaSquea"? \end{itemize} + \begin{block}{ + Join the Sprint!} + \bigskip + \hskip 1cm Saturday - Thursday, C-Base Berlin + \bigskip + \end{block} \end{frame} \begin{frame} @@ -295,7 +312,6 @@ languages, follows language evolution ``for free'' \item based on Partial Evaluation techniques \item benefits from a high-level interpreter - \item generating a dynamic compiler is easier than generating a static one! \item shares ideas with tracing JITs \end{itemize} \pause @@ -309,10 +325,19 @@ \begin{frame} \frametitle{Questions?} + Outlook: + \begin{itemize} + \item do graphical builtins, to actually start the full environment + \item Squeak-specific optimizations: + \item method-cache (should be easy with shadows) + \item JIT (automatic generation of dynamic compilers) + \item lessons learned for a "SqueaSquea"? + \end{itemize} + \bigskip \begin{block}{ - PyPy} + Join the Sprint!} \bigskip - \hskip 1cm \url{http://codespeak.net/pypy/} + \hskip 1cm Saturday - Thursday, C-Base Berlin \bigskip \end{block} \end{frame} From tverwaes at codespeak.net Fri May 16 09:26:22 2008 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Fri, 16 May 2008 09:26:22 +0200 (CEST) Subject: [pypy-svn] r54773 - in pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk: . test Message-ID: <20080516072622.9A5AA1684E4@codespeak.net> Author: tverwaes Date: Fri May 16 09:26:21 2008 New Revision: 54773 Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/classtable.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/constants.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/interpreter.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/objtable.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/primitives.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/squeakimage.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_interpreter.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_miniimage.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_shadow.py Log: bugfixes Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/classtable.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/classtable.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/classtable.py Fri May 16 09:26:21 2008 @@ -129,6 +129,6 @@ define_cls("w_LinkedList", "w_SequenceableCollection") define_cls("w_Semaphore", "w_LinkedList") define_cls("w_BlockContext", "w_ContextPart", - instvarsize=constants.BLKCTX_TEMP_FRAME_START) + instvarsize=constants.BLKCTX_STACK_START) copy_in_globals_classes_known_to_the_vm() Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/constants.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/constants.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/constants.py Fri May 16 09:26:21 2008 @@ -59,7 +59,7 @@ BLKCTX_BLOCK_ARGUMENT_COUNT_INDEX = 3 BLKCTX_INITIAL_IP_INDEX = 4 BLKCTX_HOME_INDEX = 5 -BLKCTX_TEMP_FRAME_START = 6 +BLKCTX_STACK_START = 6 # MethodContext < ContextPart MTHDCTX_METHOD = 3 Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/interpreter.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/interpreter.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/interpreter.py Fri May 16 09:26:21 2008 @@ -1,6 +1,6 @@ import py from pypy.lang.smalltalk.shadow import Invalidateable -from pypy.lang.smalltalk.shadow import ContextPartShadow +from pypy.lang.smalltalk.shadow import ContextPartShadow, MethodContextShadow, BlockContextShadow from pypy.lang.smalltalk import model, constants, primitives from pypy.lang.smalltalk import objtable from pypy.lang.smalltalk.shadow import ContextPartShadow @@ -38,6 +38,10 @@ return self._w_active_context def store_w_active_context(self, w_context): + # We can only interpret contexts of which we know the type already + s_ctx = w_context.as_context_get_shadow() + assert (isinstance(s_ctx, MethodContextShadow) or + isinstance(s_ctx, BlockContextShadow)) if self._s_active_context is not None: self._s_active_context.unnotify(self) self._s_active_context = None @@ -69,6 +73,7 @@ # translating the interpreter if not objectmodel.we_are_translated(): bytecodeimpl = BYTECODE_TABLE[next] + if self.should_trace(): if self._w_last_active_context != self.w_active_context(): cnt = 0 @@ -76,7 +81,9 @@ # AK make method while p is not objtable.w_nil: cnt += 1 - p = p.as_context_get_shadow().w_sender() + # Do not update the context + # for this action. + p = p.as_context_get_shadow(False).w_sender() self._last_indent = " " * cnt self._w_last_active_context = self.w_active_context() @@ -87,7 +94,9 @@ self._last_indent, self.s_active_context().pc(), next, bytecodeimpl.__name__,) + bytecodeimpl(self.s_active_context(), self) + else: # this is a performance optimization: when translating the # interpreter, the bytecode dispatching is not implemented as a Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py Fri May 16 09:26:21 2008 @@ -310,9 +310,9 @@ from pypy.lang.smalltalk.shadow import MethodContextShadow return self.as_special_get_shadow(MethodContextShadow, invalid) - def as_context_get_shadow(self): + def as_context_get_shadow(self, invalid=True): from pypy.lang.smalltalk.shadow import ContextPartShadow - return self.as_special_get_shadow(ContextPartShadow) + return self.as_special_get_shadow(ContextPartShadow, invalid) def as_methoddict_get_shadow(self): from pypy.lang.smalltalk.shadow import MethodDictionaryShadow @@ -458,9 +458,12 @@ def __str__(self): from pypy.lang.smalltalk.interpreter import BYTECODE_TABLE - return ("\n\nBytecode:\n---------------------\n" + - "\n".join([BYTECODE_TABLE[ord(i)].__name__ + " " + str(ord(i)) for i in self.bytes]) + - "\n---------------------\n") + j = 1 + retval = "\n\nBytecode:\n---------------------\n" + for i in self.bytes: + retval += str(j) + ": " + BYTECODE_TABLE[ord(i)].__name__ + " " + str(ord(i)) + "\n" + j += 1 + return retval + "\n---------------------\n" def invariant(self): return (W_Object.invariant(self) and @@ -481,6 +484,9 @@ def getliteralsize(self): return self.literalsize * constants.BYTES_PER_WORD + def bytecodeoffset(self): + return self.getliteralsize() + self.headersize() + def headersize(self): return constants.BYTES_PER_WORD @@ -510,6 +516,9 @@ self.w_compiledin = None self.islarge = islarge + def tempframesize(self): + return self.argsize + self.tempsize + def literalat0(self, index0): if index0 == 0: from pypy.lang.smalltalk import utility Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/objtable.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/objtable.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/objtable.py Fri May 16 09:26:21 2008 @@ -33,7 +33,7 @@ objtable = {} # XXX Used for non-PyPy way of doing become. -#objects = [] +objects = [] for name in constants.objects_in_special_object_table: name = "w_" + name Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/primitives.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/primitives.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/primitives.py Fri May 16 09:26:21 2008 @@ -502,9 +502,11 @@ @expose_primitive(BECOME, unwrap_spec=[object, object]) def func(interp, w_rcvr, w_new): -# for w_object in objtable.objects: -# w_object.become(w_rcvr, w_new) - raise PrimitiveNotYetWrittenError +# Non-PyPy way of doing become + for w_object in objtable.objects: + w_object.become(w_rcvr, w_new) + return w_rcvr + #raise PrimitiveNotYetWrittenError def fake_bytes_left(): return utility.wrap_int(2**20) # XXX we don't know how to do this :-( Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py Fri May 16 09:26:21 2008 @@ -188,9 +188,9 @@ else: raise NotImplementedError(self.instance_kind) # XXX Used for non-PyPy way of doing become. - #if store: - # from pypy.lang.smalltalk import objtable - # objtable.objects.extend([w_new]) + if store: + from pypy.lang.smalltalk import objtable + objtable.objects.extend([w_new]) return w_new # _______________________________________________________________ @@ -242,8 +242,8 @@ try: w_method = look_in_shadow.methoddict[selector] # We locally cache the method we found. - if look_in_shadow is not self: - self.methoddict[selector] = w_method + #if look_in_shadow is not self: + # self.methoddict[selector] = w_method return w_method except KeyError, e: look_in_shadow = look_in_shadow.s_superclass @@ -329,7 +329,7 @@ class SemaphoreShadow(LinkedListShadow): """A shadow for Smalltalk objects that are semaphores """ - def __init__(self, w_self, invalid): + def __init__(self, w_self, invalid=False): LinkedListShadow.__init__(self, w_self, invalid) def put_to_sleep(self, s_process): @@ -450,20 +450,29 @@ def update_shadow(self): AbstractShadow.update_shadow(self) self._stack = [self.w_self()._vars[i] - for i in range(self.stackstart() + 1, - self.stackpointer() + 1)] - self._pc = utility.unwrap_int(self.w_self()._vars[constants.CTXPART_PC_INDEX]) - self._pc -= 1 + self.w_method().getliteralsize() + for i in range(self.stackstart(), + self.stackpointer())] + self.init_pc() # Using a shadow most likely results in an invalid state for w_self self.invalidate_w_self() + def init_pc(self): + self._pc = utility.unwrap_int(self.w_self()._vars[constants.CTXPART_PC_INDEX]) + self._pc -= self.w_method().bytecodeoffset() + self._pc -= 1 + + def save_back_pc(self): + pc = self._pc + pc += 1 + pc += self.w_method().bytecodeoffset() + self.w_self()._vars[constants.CTXPART_PC_INDEX] = utility.wrap_int(pc) + def update_w_self(self): AbstractShadow.update_w_self(self) for i in range(len(self._stack)): - self.w_self()._vars[self.stackstart() + 1 + i] = self._stack[i] - self.store_stackpointer(len(self._stack) + self.stackstart()) - self.w_self()._vars[constants.CTXPART_PC_INDEX] = utility.wrap_int(self._pc + 1 + - self.w_method().getliteralsize()) + self.w_self()._vars[self.stackstart() + i] = self._stack[i] + self.store_stackpointer(len(self._stack)) + self.save_back_pc() def __init__(self, w_self, invalid): AbstractShadow.__init__(self, w_self, invalid) @@ -477,6 +486,9 @@ def stackstart(self): raise NotImplementedError() + def stackpointer_offset(self): + raise NotImplementedError() + def w_receiver(self): " Return self of the method, or the method that contains the block " return self.s_home().w_receiver() @@ -504,7 +516,11 @@ self._pc = newpc def stackpointer(self): - return utility.unwrap_int(self.w_self()._vars[constants.CTXPART_STACKP_INDEX]) + return (utility.unwrap_int(self.w_self()._vars[constants.CTXPART_STACKP_INDEX]) + + self.stackpointer_offset()) + + def stackpointer_offset(self): + raise NotImplementedError() def store_stackpointer(self, pointer): self.w_self()._vars[constants.CTXPART_STACKP_INDEX] = utility.wrap_int(pointer) @@ -630,10 +646,12 @@ def reset_stack(self): self._stack = [] - + def stackstart(self): - return (constants.BLKCTX_TEMP_FRAME_START + - self.expected_argument_count()) + return constants.BLKCTX_STACK_START + + def stackpointer_offset(self): + return constants.BLKCTX_STACK_START class MethodContextShadow(ContextPartShadow): def __init__(self, w_self, invalid): @@ -661,11 +679,11 @@ def store_w_receiver(self, w_receiver): self.w_self()._vars[constants.MTHDCTX_RECEIVER] = w_receiver - def gettemp(self, index): - return self.w_self()._vars[constants.MTHDCTX_TEMP_FRAME_START + index] + def gettemp(self, index0): + return self.w_self()._vars[constants.MTHDCTX_TEMP_FRAME_START + index0] - def settemp(self, index, w_value): - self.w_self()._vars[constants.MTHDCTX_TEMP_FRAME_START + index] = w_value + def settemp(self, index0, w_value): + self.w_self()._vars[constants.MTHDCTX_TEMP_FRAME_START + index0] = w_value def w_home(self): return self.w_self() @@ -673,8 +691,14 @@ def s_home(self): return self + def store_stackpointer(self, pointer): + ContextPartShadow.store_stackpointer(self, + pointer+self.w_method().tempframesize()) + + def stackpointer_offset(self): + return constants.MTHDCTX_TEMP_FRAME_START + def stackstart(self): w_method = self.w_method() return (constants.MTHDCTX_TEMP_FRAME_START + - w_method.argsize + - w_method.tempsize) + w_method.tempframesize()) Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/squeakimage.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/squeakimage.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/squeakimage.py Fri May 16 09:26:21 2008 @@ -204,9 +204,9 @@ from pypy.lang.smalltalk import objtable # XXX Used for non-PyPy way of doing become. - #objtable.objects.extend( - # [chunk.g_object.w_object - # for chunk in reader.chunklist]) + objtable.objects.extend( + [chunk.g_object.w_object + for chunk in reader.chunklist]) for name, idx in constants.objects_in_special_object_table.items(): objtable.objtable["w_" + name] = self.special_objects[idx] Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_interpreter.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_interpreter.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_interpreter.py Fri May 16 09:26:21 2008 @@ -799,3 +799,12 @@ [[classtable.w_CompiledMethod, primitives.OBJECT_AT, 1, "objectAt:"], [classtable.w_CompiledMethod, primitives.OBJECT_AT_PUT, 2, "objectAt:put:"]], test) + +def test_runwithtrace(): + # We run random tests with the bc_trace option turned on explicitely + from pypy.lang.smalltalk.conftest import option + bc_trace = option.bc_trace + option.bc_trace = True + test_storeAndPopReceiverVariableBytecode() + test_bc_objectAtAndAtPut() + option.bc_trace = bc_trace Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_miniimage.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_miniimage.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_miniimage.py Fri May 16 09:26:21 2008 @@ -227,19 +227,31 @@ assert w_false is objtable.w_false def test_runimage(): - py.test.skip("This method actually runs an image. Fails since no graphical primitives yet") + #py.test.skip("This method actually runs an image. Fails since no graphical primitives yet") from pypy.lang.smalltalk.shadow import SemaphoreShadow s_semaphore = SemaphoreShadow(None) s_scheduler = s_semaphore.s_scheduler() s_ap = s_scheduler.s_active_process() - s_ctx = s_ap.s_suspended_context() + s_ctx = s_ap.w_suspended_context().as_methodcontext_get_shadow() s_ap.store_w_suspended_context(objtable.w_nil) + + print "BOE" + print [x for x in enumerate(s_ctx.w_self()._vars)] + print s_ctx.stackstart() + print s_ctx.stackpointer() + + # XXX Important + # Push return value of snapshot primitive + # The interpreter must resume at the very moment the snapshot primitive + # returns. + s_ctx._stack = [objtable.w_true] + interp = interpreter.Interpreter() interp.store_w_active_context(s_ctx.w_self()) interp.interpret() def test_compile_method(): - py.test.skip("fails again because of the removed become. should work with new pypy become") + #py.test.skip("fails again because of the removed become. should work with new pypy become") sourcecode = """fib ^self < 2 ifTrue: [ 1 ] Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_shadow.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_shadow.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_shadow.py Fri May 16 09:26:21 2008 @@ -88,11 +88,10 @@ def methodcontext(w_sender=objtable.w_nil, pc=1, stackpointer=0, stacksize=5, method=method()): - stackstart = 6+method.argsize+method.tempsize # (len notation, not idx notation) - w_object = model.W_PointersObject(classtable.w_MethodContext, stackstart+stacksize) + w_object = model.W_PointersObject(classtable.w_MethodContext, constants.MTHDCTX_TEMP_FRAME_START+method.tempframesize()+stacksize) w_object.store(constants.CTXPART_SENDER_INDEX, w_sender) w_object.store(constants.CTXPART_PC_INDEX, utility.wrap_int(pc)) - w_object.store(constants.CTXPART_STACKP_INDEX, utility.wrap_int(stackstart+stackpointer)) + w_object.store(constants.CTXPART_STACKP_INDEX, utility.wrap_int(method.tempframesize()+stackpointer)) w_object.store(constants.MTHDCTX_METHOD, method) # XXX w_object.store(constants.MTHDCTX_RECEIVER_MAP, '???') @@ -119,12 +118,12 @@ assert s_object2.gettemp(0) == 'a' assert s_object.w_method() == w_m idx = s_object.stackstart() - w_object.store(idx + 1, 'f') - w_object.store(idx + 2, 'g') - w_object.store(idx + 3, 'h') + w_object.store(idx, 'f') + w_object.store(idx + 1, 'g') + w_object.store(idx + 2, 'h') s_object.update_shadow() - assert s_object.top() == 'h' assert s_object.stack() == ['f', 'g', 'h' ] + assert s_object.top() == 'h' s_object.push('i') assert s_object.top() == 'i' assert s_object.peek(1) == 'h' From tverwaes at codespeak.net Fri May 16 09:27:23 2008 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Fri, 16 May 2008 09:27:23 +0200 (CEST) Subject: [pypy-svn] r54774 - pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test Message-ID: <20080516072723.8B7F81684E4@codespeak.net> Author: tverwaes Date: Fri May 16 09:27:22 2008 New Revision: 54774 Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_miniimage.py Log: disabling the runimage test Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_miniimage.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_miniimage.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_miniimage.py Fri May 16 09:27:22 2008 @@ -227,7 +227,7 @@ assert w_false is objtable.w_false def test_runimage(): - #py.test.skip("This method actually runs an image. Fails since no graphical primitives yet") + py.test.skip("This method actually runs an image. Fails since no graphical primitives yet") from pypy.lang.smalltalk.shadow import SemaphoreShadow s_semaphore = SemaphoreShadow(None) s_scheduler = s_semaphore.s_scheduler() @@ -235,11 +235,6 @@ s_ctx = s_ap.w_suspended_context().as_methodcontext_get_shadow() s_ap.store_w_suspended_context(objtable.w_nil) - print "BOE" - print [x for x in enumerate(s_ctx.w_self()._vars)] - print s_ctx.stackstart() - print s_ctx.stackpointer() - # XXX Important # Push return value of snapshot primitive # The interpreter must resume at the very moment the snapshot primitive From tverwaes at codespeak.net Fri May 16 09:30:03 2008 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Fri, 16 May 2008 09:30:03 +0200 (CEST) Subject: [pypy-svn] r54775 - pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test Message-ID: <20080516073003.6C43F1684E4@codespeak.net> Author: tverwaes Date: Fri May 16 09:30:01 2008 New Revision: 54775 Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_shadow.py Log: fixing pc for test to work in new way Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_shadow.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_shadow.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_shadow.py Fri May 16 09:30:01 2008 @@ -137,7 +137,7 @@ def test_methodcontext(): w_m = method() # Point over 2 literals of size 4 - w_object = methodcontext(pc=9,method=w_m) + w_object = methodcontext(pc=13,method=w_m) s_object = w_object.as_methodcontext_get_shadow() assert s_object.getbytecode() == 97 assert s_object.getbytecode() == 98 From pypy-svn at codespeak.net Fri May 16 09:32:47 2008 From: pypy-svn at codespeak.net (VIAGRA ® Official Site) Date: Fri, 16 May 2008 09:32:47 +0200 (CEST) Subject: [pypy-svn] Dear pypy-svn@codespeak.net May 89% 0FF Message-ID: <20080516103838.8437.qmail@static-dsl-246.213-160-177.telecom.sk> An HTML attachment was scrubbed... URL: From afa at codespeak.net Fri May 16 09:55:19 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 16 May 2008 09:55:19 +0200 (CEST) Subject: [pypy-svn] r54776 - in pypy/dist/pypy/translator/tool: . test Message-ID: <20080516075519.81538168423@codespeak.net> Author: afa Date: Fri May 16 09:55:16 2008 New Revision: 54776 Modified: pypy/dist/pypy/translator/tool/cbuild.py pypy/dist/pypy/translator/tool/test/test_cbuild.py Log: Restore the uncontroversial part of r54748 Modified: pypy/dist/pypy/translator/tool/cbuild.py ============================================================================== --- pypy/dist/pypy/translator/tool/cbuild.py (original) +++ pypy/dist/pypy/translator/tool/cbuild.py Fri May 16 09:55:16 2008 @@ -317,7 +317,8 @@ cmdobj = build_shared_library(dist) cmdobj.inplace = True cmdobj.force = True - if sys.platform == 'win32' and sys.executable.endswith('_d.exe'): + if (sys.platform == 'win32' + and sys.executable.lower().endswith('_d.exe')): cmdobj.debug = True dist.command_obj["build_ext"] = cmdobj dist.have_run["build_ext"] = 0 Modified: pypy/dist/pypy/translator/tool/test/test_cbuild.py ============================================================================== --- pypy/dist/pypy/translator/tool/test/test_cbuild.py (original) +++ pypy/dist/pypy/translator/tool/test/test_cbuild.py Fri May 16 09:55:16 2008 @@ -45,9 +45,12 @@ { printf("%f\\n", pow(2.0, 2.0)); }''') - eci = ExternalCompilationInfo( - libraries = ['m'], - ) + if sys.platform != 'win32': + eci = ExternalCompilationInfo( + libraries = ['m'], + ) + else: + eci = ExternalCompilationInfo() output = build_executable([c_file], eci) p = Popen(output, stdout=PIPE, stderr=STDOUT) p.wait() @@ -109,7 +112,8 @@ int get() { return 42; - }'''] + }'''], + export_symbols = ['get'] ) neweci = eci.compile_shared_lib() assert len(neweci.libraries) == 1 From pypy-svn at codespeak.net Fri May 16 10:02:09 2008 From: pypy-svn at codespeak.net (VIAGRA ® Official Site) Date: Fri, 16 May 2008 10:02:09 +0200 (CEST) Subject: [pypy-svn] Dear pypy-svn@codespeak.net May 83% 0FF Message-ID: <20080516070042.16433.qmail@pppoe.77.43.145.86.ccl.perm.ru> An HTML attachment was scrubbed... URL: From antocuni at codespeak.net Fri May 16 10:07:10 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 16 May 2008 10:07:10 +0200 (CEST) Subject: [pypy-svn] r54777 - in pypy/branch/oo-jit/pypy: jit/codegen/cli jit/codegen/cli/test rpython/ootypesystem Message-ID: <20080516080710.D1DEF1684E9@codespeak.net> Author: antocuni Date: Fri May 16 10:07:08 2008 New Revision: 54777 Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/operation.py pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_interpreter.py pypy/branch/oo-jit/pypy/rpython/ootypesystem/ootype.py Log: - rename builder.parent to builder.graphbuilder - make test_compile_time_const_tuple passing Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/operation.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/codegen/cli/operation.py (original) +++ pypy/branch/oo-jit/pypy/jit/codegen/cli/operation.py Fri May 16 10:07:08 2008 @@ -17,7 +17,7 @@ if self._gv_res is None: restype = self.restype() if restype is not None: - loc = self.builder.parent.il.DeclareLocal(restype) + loc = self.builder.graphbuilder.il.DeclareLocal(restype) self._gv_res = GenLocalVar(loc) return self._gv_res @@ -41,7 +41,7 @@ def emit(self): self.pushAllArgs() - self.builder.parent.il.Emit(self.getOpCode()) + self.builder.graphbuilder.il.Emit(self.getOpCode()) self.storeResult() def getOpCode(self): @@ -59,7 +59,7 @@ def emit(self): self.pushAllArgs() - self.builder.parent.il.Emit(self.getOpCode()) + self.builder.graphbuilder.il.Emit(self.getOpCode()) self.storeResult() def getOpCode(self): @@ -82,7 +82,7 @@ return None def emit(self): - self.builder.parent.il.MarkLabel(self.label) + self.builder.graphbuilder.il.MarkLabel(self.label) class FollowLink(Operation): @@ -99,7 +99,7 @@ for i in range(len(self.outputargs_gv)): self.outputargs_gv[i].load(self.builder) self.inputargs_gv[i].store(self.builder) - self.builder.parent.il.Emit(OpCodes.Br, self.label) + self.builder.graphbuilder.il.Emit(OpCodes.Br, self.label) class Branch(Operation): @@ -116,7 +116,7 @@ def emit(self): if self.gv_cond is not None: self.gv_cond.load(self.builder) - self.builder.parent.il.Emit(self.opcode, self.label) + self.builder.graphbuilder.il.Emit(self.opcode, self.label) class Return(Operation): @@ -128,12 +128,12 @@ return None def emit(self): - retvar = self.builder.parent.retvar - retlabel = self.builder.parent.retlabel + retvar = self.builder.graphbuilder.retvar + retlabel = self.builder.graphbuilder.retlabel if self.gv_x is not None: self.gv_x.load(self.builder) - self.builder.parent.il.Emit(OpCodes.Stloc, retvar) - self.builder.parent.il.Emit(OpCodes.Br, retlabel) + self.builder.graphbuilder.il.Emit(OpCodes.Stloc, retvar) + self.builder.graphbuilder.il.Emit(OpCodes.Br, retlabel) class Call(Operation): @@ -153,10 +153,10 @@ delegate_type = class2type(self.sigtoken.funcclass) meth_invoke = delegate_type.GetMethod('Invoke') self.gv_fnptr.load(self.builder) - self.builder.parent.il.Emit(OpCodes.Castclass, delegate_type) + self.builder.graphbuilder.il.Emit(OpCodes.Castclass, delegate_type) for gv_arg in self.args_gv: gv_arg.load(self.builder) - self.builder.parent.il.EmitCall(OpCodes.Callvirt, meth_invoke, None) + self.builder.graphbuilder.il.EmitCall(OpCodes.Callvirt, meth_invoke, None) self.storeResult() @@ -230,7 +230,7 @@ if 'call' in step: return # XXX, fix this attrname = opcode2attrname(step) - body.append('self.builder.parent.il.Emit(OpCodes.%s)' % attrname) + body.append('self.builder.graphbuilder.il.Emit(OpCodes.%s)' % attrname) elif isinstance(step, cli_opcodes.MapException): return # XXX, TODO else: Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py (original) +++ pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py Fri May 16 10:07:08 2008 @@ -56,18 +56,18 @@ def load(self, builder): if self.index == 0: - builder.parent.il.Emit(OpCodes.Ldarg_0) + builder.graphbuilder.il.Emit(OpCodes.Ldarg_0) elif self.index == 1: - builder.parent.il.Emit(OpCodes.Ldarg_1) + builder.graphbuilder.il.Emit(OpCodes.Ldarg_1) elif self.index == 2: - builder.parent.il.Emit(OpCodes.Ldarg_2) + builder.graphbuilder.il.Emit(OpCodes.Ldarg_2) elif self.index == 3: - builder.parent.il.Emit(OpCodes.Ldarg_3) + builder.graphbuilder.il.Emit(OpCodes.Ldarg_3) else: - builder.parent.il.Emit(OpCodes.Ldarg, self.index) + builder.graphbuilder.il.Emit(OpCodes.Ldarg, self.index) def store(self, builder): - builder.parent.il.Emit(OpCodes.Starg, self.index) + builder.graphbuilder.il.Emit(OpCodes.Starg, self.index) def __repr__(self): return "GenArgVar(%d)" % self.index @@ -80,10 +80,10 @@ return self.v.get_LocalType() def load(self, builder): - builder.parent.il.Emit(OpCodes.Ldloc, self.v) + builder.graphbuilder.il.Emit(OpCodes.Ldloc, self.v) def store(self, builder): - builder.parent.il.Emit(OpCodes.Stloc, self.v) + builder.graphbuilder.il.Emit(OpCodes.Stloc, self.v) class IntConst(GenConst): @@ -107,7 +107,7 @@ return class2type(self.cliclass) def load(self, builder): - builder.parent.il.Emit(OpCodes.Ldc_I4, self.value) + builder.graphbuilder.il.Emit(OpCodes.Ldc_I4, self.value) def __repr__(self): return "int const=%s" % self.value @@ -127,7 +127,7 @@ return typeof(System.Double) def load(self, builder): - builder.parent.il.Emit(OpCodes.Ldc_R8, self.value) + builder.graphbuilder.il.Emit(OpCodes.Ldc_R8, self.value) def __repr__(self): return "float const=%s" % self.value @@ -144,10 +144,10 @@ return index def _load_from_array(self, builder, index, clitype): - builder.parent.il.Emit(OpCodes.Ldarg_0) - builder.parent.il.Emit(OpCodes.Ldc_I4, index) - builder.parent.il.Emit(OpCodes.Ldelem_Ref) - builder.parent.il.Emit(OpCodes.Castclass, clitype) + builder.graphbuilder.il.Emit(OpCodes.Ldarg_0) + builder.graphbuilder.il.Emit(OpCodes.Ldc_I4, index) + builder.graphbuilder.il.Emit(OpCodes.Ldelem_Ref) + builder.graphbuilder.il.Emit(OpCodes.Castclass, clitype) def getobj(self): raise NotImplementedError @@ -196,8 +196,8 @@ delegatetype = self.delegatetype index = self._get_index(builder) self._load_from_array(builder, index, holdertype) - builder.parent.il.Emit(OpCodes.Ldfld, funcfield) - builder.parent.il.Emit(OpCodes.Castclass, delegatetype) + builder.graphbuilder.il.Emit(OpCodes.Ldfld, funcfield) + builder.graphbuilder.il.Emit(OpCodes.Castclass, delegatetype) @specialize.arg(1) def revealconst(self, T): @@ -252,6 +252,11 @@ @staticmethod @specialize.memo() + def methToken(TYPE, methname): + return methname #XXX + + @staticmethod + @specialize.memo() def kindToken(T): if T is ootype.Void: return cVoid @@ -265,7 +270,10 @@ return cString elif T is ootype.Char: return cChar - elif isinstance(T, ootype.Instance): + elif isinstance(T, (ootype.Instance, + ootype.Record, + ootype.Dict, + ootype.List)): return cObject # XXX? else: assert False @@ -276,6 +284,11 @@ _, FIELD = T._lookup_field(name) return name #, RCliGenOp.kindToken(FIELD) + @staticmethod + @specialize.memo() + def allocToken(T): + return RCliGenOp.kindToken(T) + def check_no_open_mc(self): pass @@ -376,12 +389,13 @@ class BranchBuilder(GenBuilder): - def __init__(self, parent, label): - self.parent = parent + def __init__(self, graphbuilder, label): + self.graphbuilder = graphbuilder + self.rgenop = graphbuilder.rgenop self.label = label self.operations = [] self.is_open = False - self.genconsts = parent.genconsts + self.genconsts = graphbuilder.genconsts def start_writing(self): self.is_open = True @@ -436,16 +450,16 @@ op = ops.SameAs(self, args_gv[i]) self.appendop(op) args_gv[i] = op.gv_res() - label = self.parent.il.DefineLabel() + label = self.graphbuilder.il.DefineLabel() self.appendop(ops.MarkLabel(self, label)) return Label(label, args_gv) def _jump_if(self, gv_condition, opcode): - label = self.parent.il.DefineLabel() + label = self.graphbuilder.il.DefineLabel() op = ops.Branch(self, gv_condition, opcode, label) self.appendop(op) - branch = BranchBuilder(self.parent, label) - self.parent.appendbranch(branch) + branch = BranchBuilder(self.graphbuilder, label) + self.graphbuilder.appendbranch(branch) return branch def jump_if_false(self, gv_condition, args_for_jump_gv): @@ -458,11 +472,11 @@ self.operations.append(op) def end(self): - self.parent.end() + self.graphbuilder.end() def replayops(self): assert not self.is_open - il = self.parent.il + il = self.graphbuilder.il il.MarkLabel(self.label) for op in self.operations: op.emit() Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_interpreter.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_interpreter.py (original) +++ pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_interpreter.py Fri May 16 10:07:08 2008 @@ -54,7 +54,6 @@ test_arraysize = skip test_setarrayitem = skip - test_compile_time_const_tuple = skip test_green_deepfrozen_oosend = skip test_direct_oosend_with_green_self = skip test_residual_red_call = skip Modified: pypy/branch/oo-jit/pypy/rpython/ootypesystem/ootype.py ============================================================================== --- pypy/branch/oo-jit/pypy/rpython/ootypesystem/ootype.py (original) +++ pypy/branch/oo-jit/pypy/rpython/ootypesystem/ootype.py Fri May 16 10:07:08 2008 @@ -848,6 +848,8 @@ def _cast_to(self, EXPECTED_TYPE): if self.obj is None: return null(EXPECTED_TYPE) + elif EXPECTED_TYPE is Object: + return self elif isinstance(EXPECTED_TYPE, Instance): return oodowncast(EXPECTED_TYPE, self.obj) elif isinstance(EXPECTED_TYPE, SpecializableType): From antocuni at codespeak.net Fri May 16 10:11:45 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 16 May 2008 10:11:45 +0200 (CEST) Subject: [pypy-svn] r54778 - pypy/branch/oo-jit/pypy/jit/codegen/cli Message-ID: <20080516081145.4381C16844A@codespeak.net> Author: antocuni Date: Fri May 16 10:11:44 2008 New Revision: 54778 Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py Log: return the identityhash intead of dummy numbers when converting from object to integers Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py (original) +++ pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py Fri May 16 10:11:44 2008 @@ -1,4 +1,5 @@ from pypy.tool.pairtype import extendabletype +from pypy.rlib.rarithmetic import intmask from pypy.rpython.ootypesystem import ootype from pypy.rlib.objectmodel import specialize from pypy.jit.codegen.model import AbstractRGenOp, GenBuilder, GenLabel @@ -172,9 +173,9 @@ @specialize.arg(1) def revealconst(self, T): if T is ootype.Signed: - return 12345 + return ootype.ooidentityhash(self.obj) elif T is ootype.Unsigned: - return 12346 + return intmask(ootype.ooidentityhash(self.obj)) return ootype.cast_from_object(T, self.obj) From cfbolz at codespeak.net Fri May 16 10:20:43 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 16 May 2008 10:20:43 +0200 (CEST) Subject: [pypy-svn] r54779 - pypy/extradoc/talk/s3-2008 Message-ID: <20080516082043.B97981684EC@codespeak.net> Author: cfbolz Date: Fri May 16 10:20:41 2008 New Revision: 54779 Added: pypy/extradoc/talk/s3-2008/talk.pdf (contents, props changed) Log: check in the talk Added: pypy/extradoc/talk/s3-2008/talk.pdf ============================================================================== Binary file. No diff available. From cfbolz at codespeak.net Fri May 16 10:22:37 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 16 May 2008 10:22:37 +0200 (CEST) Subject: [pypy-svn] r54780 - pypy/extradoc/talk/s3-2008 Message-ID: <20080516082237.AC7B21684E9@codespeak.net> Author: cfbolz Date: Fri May 16 10:22:36 2008 New Revision: 54780 Modified: pypy/extradoc/talk/s3-2008/talk.pdf pypy/extradoc/talk/s3-2008/talk.tex Log: changes to the code Modified: pypy/extradoc/talk/s3-2008/talk.pdf ============================================================================== Binary files. No diff available. Modified: pypy/extradoc/talk/s3-2008/talk.tex ============================================================================== --- pypy/extradoc/talk/s3-2008/talk.tex (original) +++ pypy/extradoc/talk/s3-2008/talk.tex Fri May 16 10:22:36 2008 @@ -224,12 +224,12 @@ \frame[containsverbatim, plain, shrink=10]{ \begin{verbatim} bool_ops = [ - (LESSTHAN, operator.lt), - (GREATERTHAN, operator.gt), - (LESSOREQUAL, operator.le), - (GREATEROREQUAL,operator.ge), - (EQUAL, operator.eq), - (NOTEQUAL, operator.ne) + (LESSTHAN, lambda x, y: x < y), + (GREATERTHAN, lambda x, y: x > y), + (LESSOREQUAL, lambda x, y: x <= y), + (GREATEROREQUAL,lambda x, y: x >= y), + (EQUAL, lambda x, y: x == y), + (NOTEQUAL, lambda x, y: x != y) ] From antocuni at codespeak.net Fri May 16 11:14:09 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 16 May 2008 11:14:09 +0200 (CEST) Subject: [pypy-svn] r54781 - in pypy/branch/oo-jit/pypy: annotation rpython/ootypesystem rpython/ootypesystem/test Message-ID: <20080516091409.2B8762A00DE@codespeak.net> Author: antocuni Date: Fri May 16 11:14:07 2008 New Revision: 54781 Modified: pypy/branch/oo-jit/pypy/annotation/builtin.py pypy/branch/oo-jit/pypy/rpython/ootypesystem/rbuiltin.py pypy/branch/oo-jit/pypy/rpython/ootypesystem/test/test_oortype.py Log: annotator&rtyper support for ooidentityhash on ootype.Object Modified: pypy/branch/oo-jit/pypy/annotation/builtin.py ============================================================================== --- pypy/branch/oo-jit/pypy/annotation/builtin.py (original) +++ pypy/branch/oo-jit/pypy/annotation/builtin.py Fri May 16 11:14:07 2008 @@ -551,7 +551,7 @@ return SomeOOInstance(c.ootype) def ooidentityhash(i): - assert isinstance(i, SomeOOInstance) + assert isinstance(i, (SomeOOInstance, SomeOOObject)) return SomeInteger() def ooupcast(I, i): Modified: pypy/branch/oo-jit/pypy/rpython/ootypesystem/rbuiltin.py ============================================================================== --- pypy/branch/oo-jit/pypy/rpython/ootypesystem/rbuiltin.py (original) +++ pypy/branch/oo-jit/pypy/rpython/ootypesystem/rbuiltin.py Fri May 16 11:14:07 2008 @@ -42,7 +42,7 @@ resulttype = hop.r_result.lowleveltype) def rtype_ooidentityhash(hop): - assert isinstance(hop.args_s[0], annmodel.SomeOOInstance) + assert isinstance(hop.args_s[0], (annmodel.SomeOOInstance, annmodel.SomeOOObject)) vlist = hop.inputargs(hop.args_r[0]) return hop.genop('ooidentityhash', vlist, resulttype = ootype.Signed) Modified: pypy/branch/oo-jit/pypy/rpython/ootypesystem/test/test_oortype.py ============================================================================== --- pypy/branch/oo-jit/pypy/rpython/ootypesystem/test/test_oortype.py (original) +++ pypy/branch/oo-jit/pypy/rpython/ootypesystem/test/test_oortype.py Fri May 16 11:14:07 2008 @@ -350,3 +350,16 @@ res = interpret(fn, [], type_system='ootype') assert res == 42 + +def test_ooidentityhash(): + L = List(Signed) + + def fn(): + lst1 = new(L) + lst2 = new(L) + obj1 = cast_to_object(lst1) + obj2 = cast_to_object(lst2) + return ooidentityhash(obj1) == ooidentityhash(obj2) + + res = interpret(fn, [], type_system='ootype') + assert not res From antocuni at codespeak.net Fri May 16 11:25:11 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 16 May 2008 11:25:11 +0200 (CEST) Subject: [pypy-svn] r54782 - in pypy/branch/oo-jit/pypy/translator/cli: . test Message-ID: <20080516092511.D1ED21684C3@codespeak.net> Author: antocuni Date: Fri May 16 11:25:10 2008 New Revision: 54782 Modified: pypy/branch/oo-jit/pypy/translator/cli/constant.py pypy/branch/oo-jit/pypy/translator/cli/dotnet.py pypy/branch/oo-jit/pypy/translator/cli/metavm.py pypy/branch/oo-jit/pypy/translator/cli/opcodes.py pypy/branch/oo-jit/pypy/translator/cli/test/test_dotnet.py Log: remove cast_object_to_record, cast_record_to_object and fieldinfo_for_const from dotnet.py, since they are not needed anymore Modified: pypy/branch/oo-jit/pypy/translator/cli/constant.py ============================================================================== --- pypy/branch/oo-jit/pypy/translator/cli/constant.py (original) +++ pypy/branch/oo-jit/pypy/translator/cli/constant.py Fri May 16 11:25:10 2008 @@ -90,12 +90,7 @@ return BaseConstantGenerator._get_key_for_const(self, value) def _create_complex_const(self, value): - from pypy.translator.cli.dotnet import _fieldinfo - - if isinstance(value, _fieldinfo): - uniq = self.db.unique() - return CLIFieldInfoConst(self.db, value.llvalue, uniq) - elif isinstance(value, ootype._view) and isinstance(value._inst, ootype._record): + if isinstance(value, ootype._view) and isinstance(value._inst, ootype._record): self.db.cts.lltype_to_cts(value._inst._TYPE) # record the type of the record return self.record_const(value._inst) else: @@ -446,26 +441,3 @@ gen.ilasm.call_method('void %s::ll_set(object)' % self.get_type(), True) return True - -class CLIFieldInfoConst(AbstractConst): - def __init__(self, db, llvalue, count): - AbstractConst.__init__(self, db, llvalue, count) - self.name = 'FieldInfo__%d' % count - - def create_pointer(self, generator): - constgen = generator.db.constant_generator - const = constgen.record_const(self.value) - generator.ilasm.opcode('ldtoken', CONST_CLASS) - generator.ilasm.call('class [mscorlib]System.Type class [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)') - generator.ilasm.opcode('ldstr', '"%s"' % const.name) - generator.ilasm.call_method('class [mscorlib]System.Reflection.FieldInfo class [mscorlib]System.Type::GetField(string)', virtual=True) - - def get_type(self): - from pypy.translator.cli.cts import CliClassType - return CliClassType('mscorlib', 'System.Reflection.FieldInfo') - - def initialize_data(self, constgen, gen): - pass - - def record_dependencies(self): - self.db.constant_generator.record_const(self.value) Modified: pypy/branch/oo-jit/pypy/translator/cli/dotnet.py ============================================================================== --- pypy/branch/oo-jit/pypy/translator/cli/dotnet.py (original) +++ pypy/branch/oo-jit/pypy/translator/cli/dotnet.py Fri May 16 11:25:10 2008 @@ -647,76 +647,6 @@ v_inst = hop.inputarg(hop.args_r[0], arg=0) return hop.genop('oodowncast', [v_inst], resulttype = hop.r_result.lowleveltype) -def cast_record_to_object(record): - T = ootype.typeOf(record) - assert isinstance(T, ootype.Record) - return ootype._view(CLR.System.Object._INSTANCE, record) - -def cast_object_to_record(T, obj): - assert isinstance(T, ootype.Record) - assert isinstance(obj, ootype._view) - assert isinstance(obj._inst, ootype._record) - record = obj._inst - assert ootype.typeOf(record) == T - return record - -class Entry(ExtRegistryEntry): - _about_ = cast_record_to_object - - def compute_result_annotation(self, s_value): - T = s_value.ootype - assert isinstance(T, ootype.Record) - can_be_None = getattr(s_value, 'can_be_None', False) - return SomeOOInstance(CLR.System.Object._INSTANCE, can_be_None=can_be_None) - - def specialize_call(self, hop): - assert isinstance(hop.args_s[0], annmodel.SomeOOInstance) - v_obj, = hop.inputargs(*hop.args_r) - hop.exception_cannot_occur() - return hop.genop('ooupcast', [v_obj], hop.r_result.lowleveltype) - -class Entry(ExtRegistryEntry): - _about_ = cast_object_to_record - - def compute_result_annotation(self, s_type, s_value): - assert s_type.is_constant() - T = s_type.const - assert isinstance(T, ootype.Record) - can_be_None = getattr(s_value, 'can_be_None', False) - return SomeOOInstance(T, can_be_None) - - def specialize_call(self, hop): - assert hop.args_s[0].is_constant() - TYPE = hop.args_s[0].const - v_obj = hop.inputarg(hop.args_r[1], arg=1) - return hop.genop('oodowncast', [v_obj], hop.r_result.lowleveltype) - -class _fieldinfo(object): - def __init__(self, llvalue): - self._TYPE = CLR.System.Reflection.FieldInfo._INSTANCE - self.llvalue = llvalue - -def fieldinfo_for_const(const): - return _fieldinfo(const) - -class Entry(ExtRegistryEntry): - _about_ = fieldinfo_for_const - - def compute_result_annotation(self, s_const): - assert s_const.is_constant() - return SomeOOInstance(CLR.System.Reflection.FieldInfo._INSTANCE) - - def specialize_call(self, hop): - llvalue = hop.args_v[0].value - c_llvalue = hop.inputconst(ootype.Void, llvalue) - return hop.genop('cli_fieldinfo_for_const', [c_llvalue], resulttype = hop.r_result.lowleveltype) - - -class Entry(ExtRegistryEntry): - _type_ = _fieldinfo - - def compute_annotation(self): - return SomeOOInstance(CLR.System.Reflection.FieldInfo._INSTANCE) from pypy.translator.cli.query import CliNamespace CLR = CliNamespace(None) Modified: pypy/branch/oo-jit/pypy/translator/cli/metavm.py ============================================================================== --- pypy/branch/oo-jit/pypy/translator/cli/metavm.py (original) +++ pypy/branch/oo-jit/pypy/translator/cli/metavm.py Fri May 16 11:25:10 2008 @@ -249,17 +249,6 @@ generator.load(op.args[2]) generator.ilasm.store_static_field(cts_type, desc) -class _FieldInfoForConst(MicroInstruction): - def render(self, generator, op): - from pypy.translator.cli.constant import CONST_CLASS - llvalue = op.args[0].value - constgen = generator.db.constant_generator - const = constgen.record_const(llvalue) - generator.ilasm.opcode('ldtoken', CONST_CLASS) - generator.ilasm.call('class [mscorlib]System.Type class [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)') - generator.ilasm.opcode('ldstr', '"%s"' % const.name) - generator.ilasm.call_method('class [mscorlib]System.Reflection.FieldInfo class [mscorlib]System.Type::GetField(string)', virtual=True) - OOTYPE_TO_MNEMONIC = { ootype.Bool: 'i1', @@ -293,5 +282,4 @@ EventHandler = _EventHandler() GetStaticField = _GetStaticField() SetStaticField = _SetStaticField() -FieldInfoForConst = _FieldInfoForConst() CastPrimitive = _CastPrimitive() Modified: pypy/branch/oo-jit/pypy/translator/cli/opcodes.py ============================================================================== --- pypy/branch/oo-jit/pypy/translator/cli/opcodes.py (original) +++ pypy/branch/oo-jit/pypy/translator/cli/opcodes.py Fri May 16 11:25:10 2008 @@ -48,7 +48,6 @@ 'cli_eventhandler': [EventHandler], 'cli_getstaticfield': [GetStaticField], 'cli_setstaticfield': [SetStaticField], - 'cli_fieldinfo_for_const': [FieldInfoForConst], 'oois': 'ceq', 'ooisnull': [PushAllArgs, 'ldnull', 'ceq'], 'oononnull': [PushAllArgs, 'ldnull', 'ceq']+Not, Modified: pypy/branch/oo-jit/pypy/translator/cli/test/test_dotnet.py ============================================================================== --- pypy/branch/oo-jit/pypy/translator/cli/test/test_dotnet.py (original) +++ pypy/branch/oo-jit/pypy/translator/cli/test/test_dotnet.py Fri May 16 11:25:10 2008 @@ -8,7 +8,7 @@ from pypy.translator.cli.dotnet import SomeCliClass, SomeCliStaticMethod,\ NativeInstance, CLR, box, unbox, OverloadingResolver, NativeException,\ native_exc, new_array, init_array, typeof, eventhandler, clidowncast,\ - fieldinfo_for_const, classof, cast_record_to_object, cast_object_to_record + classof System = CLR.System ArrayList = CLR.System.Collections.ArrayList @@ -577,36 +577,6 @@ return f self.interpret(fn, []) - def test_fieldinfo_for_const(self): - A = ootype.Instance('A', ootype.ROOT, {'xx': ootype.Signed}) - const = ootype.new(A) - const.xx = 42 - def fn(): - fieldinfo = fieldinfo_for_const(const) - obj = fieldinfo.GetValue(None) - # get the 'xx' field by using reflection - t = obj.GetType() - x_info = t.GetField('xx') - x_value = x_info.GetValue(obj) - return unbox(x_value, ootype.Signed) - res = self.interpret(fn, []) - assert res == 42 - - def test_fieldinfo_for_const_pbc(self): - A = ootype.Instance('A', ootype.ROOT, {'xx': ootype.Signed}) - const = ootype.new(A) - fieldinfo = fieldinfo_for_const(const) - def fn(): - const.xx = 42 - obj = fieldinfo.GetValue(None) - # get the 'xx' field by using reflection - t = obj.GetType() - x_info = t.GetField('xx') - x_value = x_info.GetValue(obj) - return unbox(x_value, ootype.Signed) - res = self.interpret(fn, []) - assert res == 42 - def test_classof(self): int32_class = classof(System.Int32) def fn(): @@ -643,37 +613,6 @@ return clidowncast(box(x), System.Type).get_Name() res = self.interpret(fn, [True]) assert res == 'Int32' - - def test_cast_record(self): - T = ootype.Record({'x': ootype.Signed}) - record = ootype.new(T) - def fn(flag): - if flag: - obj = cast_record_to_object(record) - else: - obj = System.Object() - record2 = cast_object_to_record(T, obj) - return record is record2 - res = self.interpret(fn, [True]) - assert res - - def test_cast_record_pbc(self): - T = ootype.Record({'x': ootype.Signed}) - record = ootype.new(T) - record.x = 42 - obj = cast_record_to_object(record) - def fn(): - record2 = cast_object_to_record(T, obj) - return record is record2 - res = self.interpret(fn, []) - assert res - - def test_cast_record_mix_object(self): - T = ootype.Record({'x': ootype.Signed}) - NULL = ootype.null(System.Object._INSTANCE) - record = cast_record_to_object(ootype.new(T)) - assert record != NULL - assert NULL != record class TestPythonnet(TestDotnetRtyping): @@ -703,9 +642,3 @@ return t.get_Name() res = self.interpret(fn, []) assert res == 'DelegateType_int__int_2' - - def test_fieldinfo_for_const(self): - pass # it makes sense only during translation - - def test_fieldinfo_for_const_pbc(self): - pass # it makes sense only during translation From afa at codespeak.net Fri May 16 11:58:53 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 16 May 2008 11:58:53 +0200 (CEST) Subject: [pypy-svn] r54783 - pypy/dist/pypy/translator/c/src Message-ID: <20080516095853.3AC8E1684E3@codespeak.net> Author: afa Date: Fri May 16 11:58:51 2008 New Revision: 54783 Modified: pypy/dist/pypy/translator/c/src/ll_strtod.h Log: Microsoft compilers name snprintf differently. Modified: pypy/dist/pypy/translator/c/src/ll_strtod.h ============================================================================== --- pypy/dist/pypy/translator/c/src/ll_strtod.h (original) +++ pypy/dist/pypy/translator/c/src/ll_strtod.h Fri May 16 11:58:51 2008 @@ -82,6 +82,10 @@ char buffer[120]; /* this should be enough, from PyString_Format code */ int buflen = 120; +#ifdef _MSC_VER +#define snprintf _snprintf +#endif + char* LL_strtod_formatd(char *fmt, double x) { int res; res = snprintf(buffer, buflen, fmt, x); From afa at codespeak.net Fri May 16 12:03:47 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 16 May 2008 12:03:47 +0200 (CEST) Subject: [pypy-svn] r54784 - pypy/dist/pypy/rpython/module Message-ID: <20080516100347.56A501684E3@codespeak.net> Author: afa Date: Fri May 16 12:03:45 2008 New Revision: 54784 Modified: pypy/dist/pypy/rpython/module/ll_strtod.py Log: test_ll_strtod passes on win32. Modified: pypy/dist/pypy/rpython/module/ll_strtod.py ============================================================================== --- pypy/dist/pypy/rpython/module/ll_strtod.py (original) +++ pypy/dist/pypy/rpython/module/ll_strtod.py Fri May 16 12:03:45 2008 @@ -12,6 +12,7 @@ _compilation_info_ = ExternalCompilationInfo( includes = ['src/ll_strtod.h'], separate_module_sources = ['#include '], + export_symbols = ['LL_strtod_formatd', 'LL_strtod_parts_to_float'], ) class RegisterStrtod(BaseLazyRegistering): From afa at codespeak.net Fri May 16 12:05:07 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 16 May 2008 12:05:07 +0200 (CEST) Subject: [pypy-svn] r54785 - pypy/dist/pypy/rpython/module Message-ID: <20080516100507.4A9971684E9@codespeak.net> Author: afa Date: Fri May 16 12:05:05 2008 New Revision: 54785 Modified: pypy/dist/pypy/rpython/module/ll_os.py Log: test_ll_os passes on win32. Modified: pypy/dist/pypy/rpython/module/ll_os.py ============================================================================== --- pypy/dist/pypy/rpython/module/ll_os.py (original) +++ pypy/dist/pypy/rpython/module/ll_os.py Fri May 16 12:05:05 2008 @@ -613,9 +613,16 @@ [rffi.CCHARP, rffi.INT], rffi.INT) - def access_llimpl(path, mode): - error = rffi.cast(lltype.Signed, os_access(path, mode)) - return error == 0 + if sys.platform.startswith('win'): + # All files are executable on Windows + def access_llimpl(path, mode): + mode = mode & ~os.X_OK + error = rffi.cast(lltype.Signed, os_access(path, mode)) + return error == 0 + else: + def access_llimpl(path, mode): + error = rffi.cast(lltype.Signed, os_access(path, mode)) + return error == 0 def os_access_oofakeimpl(path, mode): return os.access(OOSupport.from_rstr(path), mode) From afa at codespeak.net Fri May 16 12:07:00 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 16 May 2008 12:07:00 +0200 (CEST) Subject: [pypy-svn] r54786 - pypy/dist/pypy/rpython/module Message-ID: <20080516100700.A038F1684E3@codespeak.net> Author: afa Date: Fri May 16 12:06:59 2008 New Revision: 54786 Modified: pypy/dist/pypy/rpython/module/ll_os_environ.py Log: On win32, the external variable is named '_environ'. Modified: pypy/dist/pypy/rpython/module/ll_os_environ.py ============================================================================== --- pypy/dist/pypy/rpython/module/ll_os_environ.py (original) +++ pypy/dist/pypy/rpython/module/ll_os_environ.py Fri May 16 12:06:59 2008 @@ -145,6 +145,11 @@ ) def os_get_environ(): return _os_NSGetEnviron()[0] +elif sys.platform.startswith('win'): + os_get_environ, _os_set_environ = rffi.CExternVariable( + rffi.CCHARPP, + '_environ', + ExternalCompilationInfo(includes=['stdlib.h'])) else: os_get_environ, _os_set_environ = rffi.CExternVariable(rffi.CCHARPP, 'environ', From afa at codespeak.net Fri May 16 12:12:38 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 16 May 2008 12:12:38 +0200 (CEST) Subject: [pypy-svn] r54787 - pypy/dist/pypy/rpython/lltypesystem Message-ID: <20080516101238.AAC311684E9@codespeak.net> Author: afa Date: Fri May 16 12:12:37 2008 New Revision: 54787 Modified: pypy/dist/pypy/rpython/lltypesystem/rffi.py Log: on win32, don't declare external variables, and rely on the #includes to get the proper declaration. Needed for _environ: when compiling a .exe (not a dll), _environ is actually a macro... IMO other platforms should do the same, but I cannot test them. Modified: pypy/dist/pypy/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rffi.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rffi.py Fri May 16 12:12:37 2008 @@ -13,7 +13,7 @@ from pypy.translator.tool.cbuild import ExternalCompilationInfo from pypy.translator.backendopt.canraise import RaiseAnalyzer from pypy.rpython.annlowlevel import llhelper -import os +import os, sys class UnhandledRPythonException(Exception): pass @@ -399,7 +399,8 @@ c_setter = "void %(setter_name)s (%(c_type)s v) { %(name)s = v; }" % locals() lines = ["#include <%s>" % i for i in eci.includes] - lines.append('extern %s %s;' % (c_type, name)) + if sys.platform != 'win32': + lines.append('extern %s %s;' % (c_type, name)) lines.append(c_getter) lines.append(c_setter) sources = ('\n'.join(lines),) From antocuni at codespeak.net Fri May 16 13:29:16 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 16 May 2008 13:29:16 +0200 (CEST) Subject: [pypy-svn] r54788 - in pypy/branch/oo-jit/pypy: rpython/ootypesystem translator/cli translator/cli/test Message-ID: <20080516112916.18C021684DD@codespeak.net> Author: antocuni Date: Fri May 16 13:29:13 2008 New Revision: 54788 Modified: pypy/branch/oo-jit/pypy/rpython/ootypesystem/ootype.py pypy/branch/oo-jit/pypy/translator/cli/dotnet.py pypy/branch/oo-jit/pypy/translator/cli/opcodes.py pypy/branch/oo-jit/pypy/translator/cli/test/test_dotnet.py Log: add a way to convert from ootype.Object to System.Object and back; unfortunately, it works only when translated, because during interpretation ootype objects are not generally .NET objects Modified: pypy/branch/oo-jit/pypy/rpython/ootypesystem/ootype.py ============================================================================== --- pypy/branch/oo-jit/pypy/rpython/ootypesystem/ootype.py (original) +++ pypy/branch/oo-jit/pypy/rpython/ootypesystem/ootype.py Fri May 16 13:29:13 2008 @@ -989,8 +989,8 @@ def __init__(self, INSTANCE, inst): self.__dict__['_TYPE'] = INSTANCE - assert isinstance(inst, (_instance, _record)) - assert isinstance(inst._TYPE, Record) or isSubclass(inst._TYPE, INSTANCE) + assert isinstance(inst, _instance) + assert isSubclass(inst._TYPE, INSTANCE) self.__dict__['_inst'] = inst def __repr__(self): Modified: pypy/branch/oo-jit/pypy/translator/cli/dotnet.py ============================================================================== --- pypy/branch/oo-jit/pypy/translator/cli/dotnet.py (original) +++ pypy/branch/oo-jit/pypy/translator/cli/dotnet.py Fri May 16 13:29:13 2008 @@ -648,6 +648,40 @@ return hop.genop('oodowncast', [v_inst], resulttype = hop.r_result.lowleveltype) +def cast_to_native_object(obj): + raise TypeError, "cast_to_native_object is meant to be rtyped and not called direclty" + +def cast_from_native_object(obj): + raise TypeError, "cast_from_native_object is meant to be rtyped and not called direclty" + +class Entry(ExtRegistryEntry): + _about_ = cast_to_native_object + + def compute_result_annotation(self, s_value): + assert isinstance(s_value, annmodel.SomeOOObject) + assert s_value.ootype is ootype.Object + return SomeOOInstance(CLR.System.Object._INSTANCE) + + def specialize_call(self, hop): + assert isinstance(hop.args_s[0], annmodel.SomeOOObject) + v_obj, = hop.inputargs(*hop.args_r) + hop.exception_cannot_occur() + return hop.genop('ooupcast', [v_obj], hop.r_result.lowleveltype) + +class Entry(ExtRegistryEntry): + _about_ = cast_from_native_object + + def compute_result_annotation(self, s_value): + assert isinstance(s_value, annmodel.SomeOOInstance) + assert s_value.ootype is CLR.System.Object._INSTANCE + return annmodel.SomeOOObject() + + def specialize_call(self, hop): + v_obj = hop.inputarg(hop.args_r[0], arg=0) + return hop.genop('oodowncast', [v_obj], hop.r_result.lowleveltype) + + + from pypy.translator.cli.query import CliNamespace CLR = CliNamespace(None) CLR._buildtree() Modified: pypy/branch/oo-jit/pypy/translator/cli/opcodes.py ============================================================================== --- pypy/branch/oo-jit/pypy/translator/cli/opcodes.py (original) +++ pypy/branch/oo-jit/pypy/translator/cli/opcodes.py Fri May 16 13:29:13 2008 @@ -1,8 +1,7 @@ from pypy.translator.cli.metavm import Call, CallMethod, \ IndirectCall, GetField, SetField, DownCast, NewCustomDict,\ MapException, Box, Unbox, NewArray, GetArrayElem, SetArrayElem,\ - TypeOf, CastPrimitive, EventHandler, GetStaticField, SetStaticField,\ - FieldInfoForConst + TypeOf, CastPrimitive, EventHandler, GetStaticField, SetStaticField from pypy.translator.oosupport.metavm import PushArg, PushAllArgs, StoreResult, InstructionList,\ New, RuntimeNew, CastTo, PushPrimitive, OOString, OOUnicode, OONewArray from pypy.translator.cli.cts import WEAKREF Modified: pypy/branch/oo-jit/pypy/translator/cli/test/test_dotnet.py ============================================================================== --- pypy/branch/oo-jit/pypy/translator/cli/test/test_dotnet.py (original) +++ pypy/branch/oo-jit/pypy/translator/cli/test/test_dotnet.py Fri May 16 13:29:13 2008 @@ -8,7 +8,7 @@ from pypy.translator.cli.dotnet import SomeCliClass, SomeCliStaticMethod,\ NativeInstance, CLR, box, unbox, OverloadingResolver, NativeException,\ native_exc, new_array, init_array, typeof, eventhandler, clidowncast,\ - classof + classof, cast_to_native_object, cast_from_native_object System = CLR.System ArrayList = CLR.System.Collections.ArrayList @@ -613,7 +613,21 @@ return clidowncast(box(x), System.Type).get_Name() res = self.interpret(fn, [True]) assert res == 'Int32' - + + def test_cast_native_object(self): + A = ootype.Instance("A", ootype.ROOT, {}) + def fn(): + a = ootype.new(A) + ahash = ootype.ooidentityhash(a) + obj = ootype.cast_to_object(a) + native = cast_to_native_object(obj) + name = native.GetType().get_Name() + obj2 = cast_from_native_object(native) + a2 = ootype.cast_from_object(A, obj2) + a2hash = ootype.ooidentityhash(a2) + return name, ahash == a2hash + res = self.ll_to_tuple(self.interpret(fn, [])) + assert res == ('A', True) class TestPythonnet(TestDotnetRtyping): # don't interpreter functions but execute them directly through pythonnet @@ -642,3 +656,6 @@ return t.get_Name() res = self.interpret(fn, []) assert res == 'DelegateType_int__int_2' + + def test_cast_native_object(self): + pass # it works only when translated From antocuni at codespeak.net Fri May 16 14:20:59 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 16 May 2008 14:20:59 +0200 (CEST) Subject: [pypy-svn] r54790 - in pypy/branch/oo-jit/pypy/jit/codegen/cli: . test Message-ID: <20080516122059.95267168453@codespeak.net> Author: antocuni Date: Fri May 16 14:20:57 2008 New Revision: 54790 Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/operation.py pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_interpreter.py Log: two more test passes; a lot of tests are skipped for various good reasons Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/operation.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/codegen/cli/operation.py (original) +++ pypy/branch/oo-jit/pypy/jit/codegen/cli/operation.py Fri May 16 14:20:57 2008 @@ -165,7 +165,16 @@ def __init__(self, builder, gv_obj, fieldname): self.builder = builder self.gv_obj = gv_obj - self.fieldname = fieldname + clitype = gv_obj.getCliType() + self.fieldinfo = clitype.GetField(fieldname) + + def restype(self): + return self.fieldinfo.FieldType + + def emit(self): + self.gv_obj.load(self.builder) + self.builder.graphbuilder.il.Emit(OpCodes.Ldfld, self.fieldinfo) + self.storeResult() def opcode2attrname(opcode): Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py (original) +++ pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py Fri May 16 14:20:57 2008 @@ -7,6 +7,7 @@ from pypy.jit.codegen.cli import operation as ops from pypy.jit.codegen.cli.dumpgenerator import DumpGenerator from pypy.translator.cli.dotnet import CLR, typeof, new_array, box, unbox, clidowncast, classof +from pypy.translator.cli import dotnet System = CLR.System Utils = CLR.pypy.runtime.Utils DelegateHolder = CLR.pypy.runtime.DelegateHolder @@ -158,6 +159,12 @@ def __init__(self, obj): self.obj = obj + def getCliType(self): + if self.obj == ootype.NULL: + return cObject + cliobj = dotnet.cast_to_native_object(self.obj) + return cliobj.GetType() + def getobj(self): return self.obj @@ -271,10 +278,7 @@ return cString elif T is ootype.Char: return cChar - elif isinstance(T, (ootype.Instance, - ootype.Record, - ootype.Dict, - ootype.List)): + elif isinstance(T, ootype.OOType): return cObject # XXX? else: assert False @@ -368,6 +372,9 @@ def genop_same_as(self, gv_x): return self.branches[0].genop_same_as(gv_x) + def genop_oogetfield(self, fieldtoken, gv_obj): + return self.branches[0].genop_oogetfield(fieldtoken, gv_obj) + def end(self): # render all the pending branches for branchbuilder in self.branches: @@ -440,10 +447,12 @@ self.appendop(op) return op.gv_res() -## def genop_getfield(self, fieldtoken, gv_ptr): -## pass + def genop_oogetfield(self, fieldtoken, gv_obj): + op = ops.GetField(self, gv_obj, fieldtoken) + self.appendop(op) + return op.gv_res() -## def genop_setfield(self, fieldtoken, gv_ptr, gv_value): +## def genop_oosetfield(self, fieldtoken, gv_obj, gv_value): ## pass def enter_next_block(self, args_gv): Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_interpreter.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_interpreter.py (original) +++ pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_interpreter.py Fri May 16 14:20:57 2008 @@ -48,22 +48,26 @@ test_complex_struct = skip test_degenerate_with_voids = skip test_green_with_side_effects = skip + test_direct_oosend_with_green_self = skip + test_simple_red_meth_vars_around = skip # tests still bound to lltype test_simple_array = skip test_arraysize = skip test_setarrayitem = skip - - test_green_deepfrozen_oosend = skip - test_direct_oosend_with_green_self = skip + + # these tests use oogetfield, which can't be supported without + # translation + test_simple_meth = skip + + # these tests involve promotion test_residual_red_call = skip test_residual_red_call_with_exc = skip - test_simple_meth = skip - test_simple_red_meth = skip - test_simple_red_meth_vars_around = skip test_simple_indirect_call = skip test_normalize_indirect_call = skip test_normalize_indirect_call_more = skip + + test_green_char_at_merge = skip test_self_referential_structures = skip test_known_nonzero = skip From exarkun at codespeak.net Fri May 16 18:07:22 2008 From: exarkun at codespeak.net (exarkun at codespeak.net) Date: Fri, 16 May 2008 18:07:22 +0200 (CEST) Subject: [pypy-svn] r54792 - pypy/build/bot Message-ID: <20080516160722.3298E168421@codespeak.net> Author: exarkun Date: Fri May 16 18:07:19 2008 New Revision: 54792 Added: pypy/build/bot/per-directory-py-test.py Log: replacement for find on windows Added: pypy/build/bot/per-directory-py-test.py ============================================================================== --- (empty file) +++ pypy/build/bot/per-directory-py-test.py Fri May 16 18:07:19 2008 @@ -0,0 +1,18 @@ +# Alternative to find ... -exec ... which works on Windows + +import os, sys, subprocess + +def runPyPyTests(pythonExe, rootDir, args): + command = [pythonExe, r"py\bin\py.test"] + list(args) + + for rootDir, dirs, files in os.walk(rootDir): + if "test" in dirs: + testDir = os.path.join(rootDir, "test") + command.append(testDir) + subprocess.call(command + [testDir]) + +def main(): + runPyPyTests(sys.argv[1], sys.argv[2], sys.argv[3:]) + +if __name__ == '__main__': + main() From exarkun at codespeak.net Fri May 16 18:09:12 2008 From: exarkun at codespeak.net (exarkun at codespeak.net) Date: Fri, 16 May 2008 18:09:12 +0200 (CEST) Subject: [pypy-svn] r54793 - pypy/build/bot Message-ID: <20080516160912.D3A67168421@codespeak.net> Author: exarkun Date: Fri May 16 18:09:11 2008 New Revision: 54793 Modified: pypy/build/bot/master.cfg Log: enable all the builders and use the platform specific factories Modified: pypy/build/bot/master.cfg ============================================================================== --- pypy/build/bot/master.cfg (original) +++ pypy/build/bot/master.cfg Fri May 16 18:09:11 2008 @@ -3,8 +3,8 @@ from buildbot.buildslave import BuildSlave from buildbot.status.html import WebStatus -from pypy_status import RecentlyFailingTests -from pypybuilders import PyPyBuildFactory +from pypy_status import Summary +from pypybuilders import POSIXPyPyBuildFactory, WindowsPyPyBuildFactory from slaveinfo import passwords httpPortNumber = 10408 @@ -19,18 +19,18 @@ # So I did. status = WebStatus(httpPortNumber, allowForce=True) -status.putChild('summary', RecentlyFailingTests()) +status.putChild('summary', Summary()) BuildmasterConfig = { 'slavePortnum': "tcp:10407", 'change_source': [], 'schedulers': [Nightly("nightly", [ -# "pypy-c-allworkingmodules-32", -# "pypy-c-allworkingmodules-faassen-32", -# "pypy-c-allworkingmodules-faassen-64", -# "pypy-c-allworkingmodules-faassen-winxp32"], - ], hour=19)], + "pypy-c-allworkingmodules-32", + "pypy-c-allworkingmodules-faassen-32", + "pypy-c-allworkingmodules-faassen-64", + "pypy-c-allworkingmodules-faassen-winxp32"], + hour=19)], 'status': [status], 'slaves': [BuildSlave(name, password) @@ -38,35 +38,30 @@ in passwords.iteritems()], 'builders': [ -# "name": "pypy-c-allworkingmodules-32", -# "slavenames": ["charm"], -# "builddir": "pypy-c-allworkingmodules-32", -# "factory": PyPyBuildFactory(["--boxed"], -# [], -# ["--allworkingmodules"])}, - -# {"name": "pypy-c-allworkingmodules-faassen-32", -# "slavenames": ["charm"], -# "builddir": "pypy-c-allworkingmodules-faassen-32", -# "factory": PyPyBuildFactory(None, -# ["--gc=semispace"], -# ["--allworkingmodules", -# "--faassen"])}, + {"name": "pypy-c-allworkingmodules-32", + "slavenames": ["charm"], + "builddir": "pypy-c-allworkingmodules-32", + "factory": POSIXPyPyBuildFactory( + ["--boxed"], [], ["--allworkingmodules"])}, + + {"name": "pypy-c-allworkingmodules-faassen-32", + "slavenames": ["charm"], + "builddir": "pypy-c-allworkingmodules-faassen-32", + "factory": POSIXPyPyBuildFactory( + None, ["--gc=hybrid", "--gcrootfinder=asmgcc"], + ["--allworkingmodules", "--faassen"])}, {"name": "pypy-c-allworkingmodules-faassen-64", - "slavenames": [], + "slavenames": ["linux-dvs0"], "builddir": "pypy-c-allworkingmodules-faassen-64", - "factory": PyPyBuildFactory(["--boxed"], - [], - ["--allworkingmodules", - "--faassen"])}, - -# {"name": "pypy-c-allworkingmodules-faassen-winxp32", -# "slavenames": ["winxp32-py2.5"], -# "builddir": "pypy-c-allworkingmodules-faassen-winxp32", -# "factory": PyPyBuildFactory(None, -# [], -# ["--allworkingmodules"])}, + "factory": POSIXPyPyBuildFactory( + ["--boxed"], [], ["--allworkingmodules", "--faassen"])}, + + {"name": "pypy-c-allworkingmodules-faassen-winxp32", + "slavenames": ["winxp32-py2.5"], + "builddir": "pypy-c-allworkingmodules-faassen-winxp32", + "factory": WindowsPyPyBuildFactory( + ["--boxed"], [], ["--allworkingmodules"])}, ], 'buildbotURL': 'http://office.divmod.com:%d/' % (httpPortNumber,), From exarkun at codespeak.net Fri May 16 18:11:06 2008 From: exarkun at codespeak.net (exarkun at codespeak.net) Date: Fri, 16 May 2008 18:11:06 +0200 (CEST) Subject: [pypy-svn] r54794 - pypy/build/bot Message-ID: <20080516161106.504BF398008@codespeak.net> Author: exarkun Date: Fri May 16 18:11:03 2008 New Revision: 54794 Modified: pypy/build/bot/pypybuilders.py Log: platform specific build factories Modified: pypy/build/bot/pypybuilders.py ============================================================================== --- pypy/build/bot/pypybuilders.py (original) +++ pypy/build/bot/pypybuilders.py Fri May 16 18:11:03 2008 @@ -6,7 +6,7 @@ from buildbot.steps.transfer import FileUpload, FileDownload from buildbot.steps.python_twisted import Trial -from bot.netstring import netstringparser +from netstring import netstringparser from twisted.spread.banana import decode, encode from twisted.spread.jelly import unjelly, jelly @@ -48,11 +48,6 @@ TEST_PACKAGE = object() TEST_ARGUMENTS = object() - command = [ - "find", TEST_PACKAGE, "-name", "test", "-type", "d", "-exec", - PYTHON_EXECUTABLE, - "py/bin/py.test", "--session=MySession", TEST_ARGUMENTS, "{}", ";"] - haltOnFailure = False def __init__(self, testPackage, testArguments, workdir="build/pypy-src", @@ -70,40 +65,24 @@ stdout = ''.join(log.getChunks(channels=[LOG_CHANNEL_STDOUT], onlyText=True)) create_summary(stdout, self.addCompleteLog) - return - - resultLists = { - 'passed': [], - 'failed': [], - 'skipped': [], - } - weird = [] - results = netstringparser(stdout) - while True: - try: - testName = results.next() - outcome = results.next() - if outcome == 'failed': - message = results.next() - else: - message = None - except StopIteration: - break - else: - if outcome in resultLists: - resultLists[outcome].append(testName) - else: - weird.append(testName) - resultLists['weird'] = weird - - for testGroup, testNames in resultLists.iteritems(): - if testNames: - self.addCompleteLog( - '%d %s' % (len(testNames), testGroup), - '\n'.join(testNames)) +class POSIXPyTest(PyTest): + command = [ + "find", PyTest.TEST_PACKAGE, "-name", "test", "-type", "d", "-exec", + PyTest.PYTHON_EXECUTABLE, + "py/bin/py.test", "--session=MySession", PyTest.TEST_ARGUMENTS, "{}", + ";"] + + + +class WindowsPyTest(PyTest): + command = [ + "per-directory-py-test.py", + PyTest.PYTHON_EXECUTABLE, PyTest.TEST_PACKAGE, + PyTest.TEST_ARGUMENTS] + class PySwitch(ShellCommand): @@ -120,6 +99,8 @@ class PyPyBuildFactory(BuildFactory): + PyTestStep = None + def __init__(self, pytestArguments, translationArguments, targetArguments, *a, **kw): BuildFactory.__init__(self, *a, **kw) @@ -133,7 +114,7 @@ self.addStep(PySwitch) self.addStep( FileDownload, - mastersrc="netstring-conftest.py", + mastersrc="netstring_conftest.py", slavedest="conftest.py", workdir="build/pypy-src") @@ -144,19 +125,25 @@ workdir="build/pypy-src") self.addStep( + FileDownload, + mastersrc="per-directory-py-test.py", + slavedest="per-directory-py-test.py", + workdir="build/pypy-src") + + self.addStep( Translate, translationArgs=translationArguments, targetArgs=targetArguments) if pytestArguments is not None: self.addStep( - PyTest, + self.PyTestStep, testPackage="pypy", testArguments=pytestArguments, timeout=60 * 60) self.addStep( - PyTest, + self.PyTestStep, python="pypy/translator/goal/pypy-c", testPackage="pypy", # Exclude --boxed if it was specified, because -A shouldn't @@ -164,9 +151,9 @@ testArguments=["-A"] + list(arg for arg in pytestArguments if arg != "--boxed"), timeout=60 * 60) - # self.addStep(FileUpload, - # slavesrc="pypy-src/pypy/translator/goal/pypy-c", - # masterdest="pypy-c") + self.addStep(FileUpload, + slavesrc="pypy-src/pypy/translator/goal/pypy-c", + masterdest="pypy-c") self.addStep( SVN, @@ -183,3 +170,13 @@ trial="../../../../Twisted-src/bin/trial", tests=["twisted"], env={"PATH": "."}) + + + +class POSIXPyPyBuildFactory(PyPyBuildFactory): + PyTestStep = POSIXPyTest + + + +class WindowsPyPyBuildFactory(PyPyBuildFactory): + PyTestStep = WindowsPyTest From exarkun at codespeak.net Fri May 16 18:14:49 2008 From: exarkun at codespeak.net (exarkun at codespeak.net) Date: Fri, 16 May 2008 18:14:49 +0200 (CEST) Subject: [pypy-svn] r54795 - pypy/build/bot Message-ID: <20080516161449.D802B16841E@codespeak.net> Author: exarkun Date: Fri May 16 18:14:49 2008 New Revision: 54795 Modified: pypy/build/bot/per-directory-py-test.py Log: Perhaps this will help Modified: pypy/build/bot/per-directory-py-test.py ============================================================================== --- pypy/build/bot/per-directory-py-test.py (original) +++ pypy/build/bot/per-directory-py-test.py Fri May 16 18:14:49 2008 @@ -8,7 +8,6 @@ for rootDir, dirs, files in os.walk(rootDir): if "test" in dirs: testDir = os.path.join(rootDir, "test") - command.append(testDir) subprocess.call(command + [testDir]) def main(): From afa at codespeak.net Fri May 16 19:34:07 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 16 May 2008 19:34:07 +0200 (CEST) Subject: [pypy-svn] r54796 - pypy/dist/pypy/rlib Message-ID: <20080516173407.01A54398008@codespeak.net> Author: afa Date: Fri May 16 19:34:06 2008 New Revision: 54796 Added: pypy/dist/pypy/rlib/rwin32.py Modified: pypy/dist/pypy/rlib/libffi.py Log: Start a new rlib\rwin32 module, to hold common types and functions from the win32 API, and use it in libffi. The module should be importable from all platforms, the WIN32 symbol will always be available: from pypy.rlib import rwin32 if rwin32.WIN32: ... Tests will follow. Modified: pypy/dist/pypy/rlib/libffi.py ============================================================================== --- pypy/dist/pypy/rlib/libffi.py (original) +++ pypy/dist/pypy/rlib/libffi.py Fri May 16 19:34:06 2008 @@ -14,6 +14,9 @@ _MS_WINDOWS = os.name == "nt" +if _MS_WINDOWS: + from pypy.rlib import rwin32 + if not _MS_WINDOWS: includes = ['dlfcn.h', 'ffi.h'] include_dirs = [] @@ -75,10 +78,6 @@ ffi_closure = rffi_platform.Struct('ffi_closure', []) - if _MS_WINDOWS: - DWORD = rffi_platform.SimpleType("DWORD", rffi.UINT) - BOOL = rffi_platform.SimpleType("BOOL", rffi.LONG) - def add_simple_type(type_name): for name in ['size', 'alignment', 'type']: setattr(CConfig, type_name + '_' + name, @@ -198,32 +197,30 @@ return res if _MS_WINDOWS: - LoadLibrary = winexternal('LoadLibraryA', [rffi.CCHARP], rffi.VOIDP) - GetProcAddress = winexternal('GetProcAddress', [rffi.VOIDP, rffi.CCHARP], rffi.VOIDP) - FreeLibrary = winexternal('FreeLibrary', [rffi.VOIDP], cConfig.BOOL) - GetLastError = winexternal('GetLastError', [], cConfig.DWORD) - def dlopen(name): - res = LoadLibrary(name) + res = rwin32.LoadLibrary(name) if not res: # XXX format error message - raise WindowsError(2, GetLastError()) + raise WindowsError(2, rwin32.GetLastError()) return res def dlclose(handle): - res = FreeLibrary(handle) + res = rwin32.FreeLibrary(handle) if res: return -1 else: return 0 def dlsym(handle, name): - res = GetProcAddress(handle, name) + res = rwin32.GetProcAddress(handle, name) if not res: raise KeyError(name) # XXX rffi.cast here... return res + FormatError = rwin32.FormatError + LoadLibrary = rwin32.LoadLibrary + FFI_OK = cConfig.FFI_OK FFI_BAD_TYPEDEF = cConfig.FFI_BAD_TYPEDEF FFI_DEFAULT_ABI = rffi.cast(rffi.USHORT, cConfig.FFI_DEFAULT_ABI) @@ -323,8 +320,9 @@ closureHeap = ClosureHeap() -FUNCFLAG_STDCALL = 0 -FUNCFLAG_CDECL = 1 # for WINAPI calls +FUNCFLAG_STDCALL = 0 +FUNCFLAG_CDECL = 1 # for WINAPI calls +FUNCFLAG_PYTHONAPI = 4 class AbstractFuncPtr(object): ll_cif = lltype.nullptr(FFI_CIFP.TO) Added: pypy/dist/pypy/rlib/rwin32.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rlib/rwin32.py Fri May 16 19:34:06 2008 @@ -0,0 +1,81 @@ +""" External functions accessing the win32 api. +Common types, functions from core win32 libraries, such as kernel32 +""" + +from pypy.rpython.tool import rffi_platform +from pypy.translator.tool.cbuild import ExternalCompilationInfo +from pypy.rpython.lltypesystem import lltype, rffi +import os + +# This module can be imported on any platform, +# but most symbols are not usable... +WIN32 = os.name == "nt" + +if WIN32: + eci = ExternalCompilationInfo( + includes = ['windows.h'], + libraries = ['kernel32'], + ) +else: + eci = ExternalCompilationInfo() + +class CConfig: + _compilation_info_ = eci + + if WIN32: + DWORD = rffi_platform.SimpleType("DWORD", rffi.UINT) + BOOL = rffi_platform.SimpleType("BOOL", rffi.LONG) + + HANDLE = rffi_platform.SimpleType("HANDLE", rffi.VOIDP) + HLOCAL = rffi_platform.SimpleType("HLOCAL", rffi.VOIDP) + + DEFAULT_LANGUAGE = rffi_platform.ConstantInteger( + "MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT)") + + for name in """FORMAT_MESSAGE_ALLOCATE_BUFFER FORMAT_MESSAGE_FROM_SYSTEM + """.split(): + locals()[name] = rffi_platform.ConstantInteger(name) + + +for k, v in rffi_platform.configure(CConfig).items(): + globals()[k] = v + +def winexternal(name, args, result): + return rffi.llexternal(name, args, result, compilation_info=eci, calling_conv='win') + +if WIN32: + GetLastError = winexternal('GetLastError', [], DWORD) + + LoadLibrary = winexternal('LoadLibraryA', [rffi.CCHARP], rffi.VOIDP) + GetProcAddress = winexternal('GetProcAddress', + [rffi.VOIDP, rffi.CCHARP], + rffi.VOIDP) + FreeLibrary = winexternal('FreeLibrary', [rffi.VOIDP], BOOL) + + LocalFree = winexternal('LocalFree', [HLOCAL], DWORD) + + FormatMessage = winexternal( + 'FormatMessageA', + [DWORD, rffi.VOIDP, DWORD, DWORD, rffi.CCHARP, DWORD, rffi.VOIDP], + DWORD) + + + # A bit like strerror... + def FormatError(code): + "Return a message corresponding to the given Windows error code." + buf = lltype.malloc(rffi.VOIDPP.TO, 1, flavor='raw') + + msglen = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM, + None, + code, + DEFAULT_LANGUAGE, + rffi.cast(rffi.VOIDP, buf), + 0, None) + + # FormatMessage always appends a \n. + msglen -= 1 + + result = ''.join([buf[0][i] for i in range(msglen)]) + LocalFree(buf[0]) + return result From afa at codespeak.net Fri May 16 19:50:47 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 16 May 2008 19:50:47 +0200 (CEST) Subject: [pypy-svn] r54797 - in pypy/dist/pypy: lib/_ctypes lib/ctypes module/_rawffi rpython/lltypesystem Message-ID: <20080516175047.3E4732A00DB@codespeak.net> Author: afa Date: Fri May 16 19:50:43 2008 New Revision: 54797 Modified: pypy/dist/pypy/lib/_ctypes/__init__.py pypy/dist/pypy/lib/_ctypes/builtin.py pypy/dist/pypy/lib/ctypes/__init__.py pypy/dist/pypy/module/_rawffi/__init__.py pypy/dist/pypy/module/_rawffi/interp_rawffi.py pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py Log: On win32, ctypes now works on top of py.py! bin\py.py --withmod-_rawffi can import ctypes, and basic operations seem to work. I Hope I did not break other platforms... Todo: write a version of ll2ctypes.get_libc_name that does not depend on CPython ctypes. Modified: pypy/dist/pypy/lib/_ctypes/__init__.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/__init__.py (original) +++ pypy/dist/pypy/lib/_ctypes/__init__.py Fri May 16 19:50:43 2008 @@ -11,9 +11,15 @@ set_conversion_mode, _wstring_at_addr from _ctypes.union import Union +import os as _os + +if _os.name in ("nt", "ce"): + from _rawffi import FormatError + from _rawffi import check_HRESULT as _check_HRESULT + +from _rawffi import FUNCFLAG_STDCALL, FUNCFLAG_CDECL, FUNCFLAG_PYTHONAPI + __version__ = '1.0.2' #XXX platform dependant? RTLD_LOCAL = 0 RTLD_GLOBAL = 256 -FUNCFLAG_CDECL = 1 -FUNCFLAG_PYTHONAPI = 4 Modified: pypy/dist/pypy/lib/_ctypes/builtin.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/builtin.py (original) +++ pypy/dist/pypy/lib/_ctypes/builtin.py Fri May 16 19:50:43 2008 @@ -5,8 +5,8 @@ encoding = 'ascii' errors = 'strict' -_memmove_addr = ('memmove', 'libc.so.6') -_memset_addr = ('memset', 'libc.so.6') +_memmove_addr = ('memmove', _rawffi.libc_name) +_memset_addr = ('memset', _rawffi.libc_name) def _string_at_addr(addr, lgt): # address here can be almost anything Modified: pypy/dist/pypy/lib/ctypes/__init__.py ============================================================================== --- pypy/dist/pypy/lib/ctypes/__init__.py (original) +++ pypy/dist/pypy/lib/ctypes/__init__.py Fri May 16 19:50:43 2008 @@ -106,7 +106,6 @@ return CFunctionType if _os.name in ("nt", "ce"): - from _ctypes import LoadLibrary as _dlopen from _ctypes import FUNCFLAG_STDCALL as _FUNCFLAG_STDCALL if _os.name == "ce": # 'ce' doesn't have the stdcall calling convention @@ -127,9 +126,7 @@ if WINFUNCTYPE.__doc__: WINFUNCTYPE.__doc__ = CFUNCTYPE.__doc__.replace("CFUNCTYPE", "WINFUNCTYPE") -elif _os.name == "posix": - from _ctypes import dlopen as _dlopen - +from _ctypes import dlopen as _dlopen from _ctypes import sizeof, byref, addressof, alignment, resize from _ctypes import _SimpleCData Modified: pypy/dist/pypy/module/_rawffi/__init__.py ============================================================================== --- pypy/dist/pypy/module/_rawffi/__init__.py (original) +++ pypy/dist/pypy/module/_rawffi/__init__.py Fri May 16 19:50:43 2008 @@ -30,3 +30,24 @@ appleveldefs = { 'SegfaultException' : 'error.SegfaultException', } + + def buildloaders(cls): + from pypy.module._rawffi import interp_rawffi + + if hasattr(interp_rawffi, 'FormatError'): + Module.interpleveldefs['FormatError'] = 'interp_rawffi.FormatError' + if hasattr(interp_rawffi, 'check_HRESULT'): + Module.interpleveldefs['check_HRESULT'] = 'interp_rawffi.check_HRESULT' + + from pypy.rlib import libffi + for name in ['FUNCFLAG_STDCALL', 'FUNCFLAG_CDECL', 'FUNCFLAG_PYTHONAPI', + ]: + if hasattr(libffi, name): + Module.interpleveldefs[name] = "space.wrap(%r)" % getattr(libffi, name) + + # Name of C runtime library + from pypy.rpython.lltypesystem.ll2ctypes import get_libc_name + Module.interpleveldefs['libc_name'] = "space.wrap(%r)" % get_libc_name() + + super(Module, cls).buildloaders() + buildloaders = classmethod(buildloaders) Modified: pypy/dist/pypy/module/_rawffi/interp_rawffi.py ============================================================================== --- pypy/dist/pypy/module/_rawffi/interp_rawffi.py (original) +++ pypy/dist/pypy/module/_rawffi/interp_rawffi.py Fri May 16 19:50:43 2008 @@ -2,13 +2,18 @@ from pypy.interpreter.baseobjspace import W_Root, ObjSpace, Wrappable, \ Arguments from pypy.interpreter.error import OperationError, wrap_oserror -from pypy.interpreter.gateway import interp2app +from pypy.interpreter.gateway import interp2app, NoneNotWrapped from pypy.interpreter.typedef import TypeDef, GetSetProperty from pypy.rlib.libffi import * from pypy.rpython.lltypesystem import lltype, rffi from pypy.rlib.unroll import unrolling_iterable +try: + from pypy.rlib import rwin32 +except: + rwin32 = None + from pypy.tool.sourcetools import func_with_new_name from pypy.rlib.rarithmetic import intmask, r_uint, r_singlefloat from pypy.module._rawffi.tracker import tracker @@ -452,3 +457,13 @@ s = rffi.charpsize2str(rffi.cast(rffi.CCHARP, address), maxlength) return space.wrap(s) charp2rawstring.unwrap_spec = [ObjSpace, r_uint, int] + +def FormatError(space, code): + return space.wrap(rwin32.FormatError(code)) +FormatError.unwrap_spec = [ObjSpace, int] + +def check_HRESULT(space, hresult): + if rwin32.FAILED(hresult): + raise OperationError(space.w_WindowsError, space.wrap(hresult)) + return space.wrap(hresult) +check_HRESULT.unwrap_spec = [ObjSpace, int] Modified: pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py Fri May 16 19:50:43 2008 @@ -518,30 +518,33 @@ # __________ the standard C library __________ if ctypes: - if sys.platform == 'win32': - # Parses sys.version and deduces the version of the compiler - import distutils.msvccompiler - version = distutils.msvccompiler.get_build_version() - if version is None: - # This logic works with official builds of Python. - if sys.version_info < (2, 4): - clibname = 'msvcrt' - else: - clibname = 'msvcr71' - else: - if version <= 6: - clibname = 'msvcrt' + def get_libc_name(): + if sys.platform == 'win32': + # Parses sys.version and deduces the version of the compiler + import distutils.msvccompiler + version = distutils.msvccompiler.get_build_version() + if version is None: + # This logic works with official builds of Python. + if sys.version_info < (2, 4): + clibname = 'msvcrt' + else: + clibname = 'msvcr71' else: - clibname = 'msvcr%d' % (version * 10) + if version <= 6: + clibname = 'msvcrt' + else: + clibname = 'msvcr%d' % (version * 10) + + # If python was built with in debug mode + import imp + if imp.get_suffixes()[0][0] == '_d.pyd': + clibname += 'd' - # If python was built with in debug mode - import imp - if imp.get_suffixes()[0][0] == '_d.pyd': - clibname += 'd' - - standard_c_lib = ctypes.cdll.LoadLibrary(clibname+'.dll') - else: - standard_c_lib = ctypes.cdll.LoadLibrary(ctypes.util.find_library('c')) + return clibname+'.dll' + else: + return ctypes.util.find_library('c') + + standard_c_lib = ctypes.cdll.LoadLibrary(get_libc_name()) # ____________________________________________ From afa at codespeak.net Fri May 16 20:50:49 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 16 May 2008 20:50:49 +0200 (CEST) Subject: [pypy-svn] r54798 - pypy/dist/pypy/rlib Message-ID: <20080516185049.AFCED168501@codespeak.net> Author: afa Date: Fri May 16 20:50:45 2008 New Revision: 54798 Modified: pypy/dist/pypy/rlib/libffi.py pypy/dist/pypy/rlib/rwin32.py Log: Translation fixes for _rawffi on win32. The translation went almost to the end! the process failed in gen_makefile(), which is of no use on windows :-( Modified: pypy/dist/pypy/rlib/libffi.py ============================================================================== --- pypy/dist/pypy/rlib/libffi.py (original) +++ pypy/dist/pypy/rlib/libffi.py Fri May 16 20:50:45 2008 @@ -5,7 +5,7 @@ from pypy.rpython.tool import rffi_platform from pypy.rpython.lltypesystem import lltype, rffi from pypy.rlib.unroll import unrolling_iterable -from pypy.rlib.rarithmetic import intmask +from pypy.rlib.rarithmetic import intmask, r_uint from pypy.rlib.objectmodel import we_are_translated from pypy.tool.autopath import pypydir from pypy.translator.tool.cbuild import ExternalCompilationInfo @@ -346,7 +346,7 @@ if _MS_WINDOWS: # This little trick works correctly with MSVC. # It returns small structures in registers - if restype.c_type == FFI_TYPE_STRUCT: + if r_uint(restype.c_type) == FFI_TYPE_STRUCT: if restype.c_size <= 4: restype = ffi_type_sint32 elif restype.c_size <= 8: Modified: pypy/dist/pypy/rlib/rwin32.py ============================================================================== --- pypy/dist/pypy/rlib/rwin32.py (original) +++ pypy/dist/pypy/rlib/rwin32.py Fri May 16 20:50:45 2008 @@ -25,6 +25,7 @@ if WIN32: DWORD = rffi_platform.SimpleType("DWORD", rffi.UINT) BOOL = rffi_platform.SimpleType("BOOL", rffi.LONG) + HRESULT = rffi_platform.SimpleType("HRESULT", rffi.LONG) HANDLE = rffi_platform.SimpleType("HANDLE", rffi.VOIDP) HLOCAL = rffi_platform.SimpleType("HLOCAL", rffi.VOIDP) @@ -79,3 +80,7 @@ result = ''.join([buf[0][i] for i in range(msglen)]) LocalFree(buf[0]) return result + + def FAILED(hr): + return rffi.cast(HRESULT, hr) < 0 + From hpk at codespeak.net Sat May 17 10:13:47 2008 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sat, 17 May 2008 10:13:47 +0200 (CEST) Subject: [pypy-svn] r54803 - pypy/extradoc/sprintinfo/berlin-2008 Message-ID: <20080517081347.EBC4E2A017B@codespeak.net> Author: hpk Date: Sat May 17 10:13:45 2008 New Revision: 54803 Modified: pypy/extradoc/sprintinfo/berlin-2008/people.txt Log: my planned time Modified: pypy/extradoc/sprintinfo/berlin-2008/people.txt ============================================================================== --- pypy/extradoc/sprintinfo/berlin-2008/people.txt (original) +++ pypy/extradoc/sprintinfo/berlin-2008/people.txt Sat May 17 10:13:45 2008 @@ -19,6 +19,7 @@ Carl Friedrich Bolz 14-22 Die Fabrik Antonio Cuni 19-24 A&O Hotel Mitte Alexander Schremmer 16(night)-18 www.singer109.com +Holger Krekel 19/evening-22 private ==================== ============== ======================= People on the following list were present at previous sprints: From cfbolz at codespeak.net Sat May 17 10:58:27 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sat, 17 May 2008 10:58:27 +0200 (CEST) Subject: [pypy-svn] r54804 - pypy/extradoc/sprintinfo/berlin-2008 Message-ID: <20080517085827.831C7168416@codespeak.net> Author: cfbolz Date: Sat May 17 10:58:23 2008 New Revision: 54804 Added: pypy/extradoc/sprintinfo/berlin-2008/planning.txt (contents, props changed) Log: (all): planning for today Added: pypy/extradoc/sprintinfo/berlin-2008/planning.txt ============================================================================== --- (empty file) +++ pypy/extradoc/sprintinfo/berlin-2008/planning.txt Sat May 17 10:58:23 2008 @@ -0,0 +1,40 @@ + + +Berlin Sprint +============= + +People Present: + + - Carl Friedrich + - Toon + - Armin + - Peter + - Karl + - Camillo + - Stephan + - Alexander + - Maciek + - Felix + - Samuele + - Adrian + +Tasks: + + - gameboy emulator + - adding sdl bindings to rpython (Camillo, Karl, Armin) + - django porting + - making sqlite-ctypes work on PyPy (Samuele, Felix, Maciek) + - hybrid-io-improvements branch + - work on SPy, decide about the branch (Alexander, Toon, Carl Friedrich) + - complete Stackless interface (Adrian, Stephan, Peter) + - discussions/starting on separate compilation + + + - work on PyPy's JIT generator: we are refactoring parts of the + compiling logic, in ways that may also allow generating better + machine code for loops (people or aliens with knowledge on + compilers and SSA, welcome) + + - trying some large pure-Python applications or libraries on PyPy and + fixing the resulting bugs. Possibilities are Zope 3, Django and + others. From arigo at codespeak.net Sat May 17 11:16:34 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 17 May 2008 11:16:34 +0200 (CEST) Subject: [pypy-svn] r54806 - pypy/dist/pypy/rlib/rsdl Message-ID: <20080517091634.20CDA1684CE@codespeak.net> Author: arigo Date: Sat May 17 11:16:33 2008 New Revision: 54806 Removed: pypy/dist/pypy/rlib/rsdl/ Log: Remove this old attempt at binding to the SDL. From arigo at codespeak.net Sat May 17 11:36:58 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 17 May 2008 11:36:58 +0200 (CEST) Subject: [pypy-svn] r54808 - in pypy/dist/pypy/rlib/rsdl: . test Message-ID: <20080517093658.80DB9168556@codespeak.net> Author: arigo Date: Sat May 17 11:36:57 2008 New Revision: 54808 Added: pypy/dist/pypy/rlib/rsdl/ (props changed) pypy/dist/pypy/rlib/rsdl/RSDL.py (contents, props changed) pypy/dist/pypy/rlib/rsdl/__init__.py (contents, props changed) pypy/dist/pypy/rlib/rsdl/test/ (props changed) pypy/dist/pypy/rlib/rsdl/test/__init__.py (contents, props changed) pypy/dist/pypy/rlib/rsdl/test/test_basic.py (contents, props changed) Log: (karlb, cami, arigo) Start working on a direct rffi binding for the SDL. Added: pypy/dist/pypy/rlib/rsdl/RSDL.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rlib/rsdl/RSDL.py Sat May 17 11:36:57 2008 @@ -0,0 +1,25 @@ +from pypy.rpython.lltypesystem import lltype, rffi +from pypy.rpython.tool import rffi_platform as platform +from pypy.translator.tool.cbuild import ExternalCompilationInfo + +eci = ExternalCompilationInfo( + includes = ['SDL.h'], + include_dirs = ['/usr/include/SDL'], + libraries = ['SDL'], +) + +def external(name, args, result): + return rffi.llexternal(name, args, result, compilation_info=eci) + +class CConfig: + _compilation_info_ = eci + + Uint32 = platform.SimpleType('Uint32', rffi.INT) + + INIT_VIDEO = platform.ConstantInteger('SDL_INIT_VIDEO') + +globals().update(platform.configure(CConfig)) + + +Init = external('SDL_Init', [Uint32], rffi.INT) +Quit = external('SDL_Quit', [], lltype.Void) Added: pypy/dist/pypy/rlib/rsdl/__init__.py ============================================================================== Added: pypy/dist/pypy/rlib/rsdl/test/__init__.py ============================================================================== Added: pypy/dist/pypy/rlib/rsdl/test/test_basic.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rlib/rsdl/test/test_basic.py Sat May 17 11:36:57 2008 @@ -0,0 +1,7 @@ +import py +from pypy.rlib.rsdl import RSDL + + +def test_sdl_init(): + assert RSDL.Init(RSDL.INIT_VIDEO) >= 0 + RSDL.Quit() From tverwaes at codespeak.net Sat May 17 12:05:09 2008 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Sat, 17 May 2008 12:05:09 +0200 (CEST) Subject: [pypy-svn] r54811 - pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk Message-ID: <20080517100509.3B26C168544@codespeak.net> Author: tverwaes Date: Sat May 17 12:05:07 2008 New Revision: 54811 Added: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/wrapper.py Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py Log: (cfbolz, tverwaes, xorAxAx) moving from shadows to wrappers for non-caching shadows Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py Sat May 17 12:05:07 2008 @@ -281,168 +281,6 @@ "CompiledMethods only for now") self.methoddict[selector] = w_compiledmethod -class LinkedListShadow(AbstractShadow): - def __init__(self, w_self, invalid): - AbstractShadow.__init__(self, w_self, invalid) - - def w_firstlink(self): - w_v = self.w_self()._vars[constants.FIRST_LINK_INDEX] - assert isinstance(w_v, model.W_PointersObject) - return w_v - - def store_w_firstlink(self, w_object): - self.w_self()._vars[constants.FIRST_LINK_INDEX] = w_object - - def w_lastlink(self): - w_v = self.w_self()._vars[constants.LAST_LINK_INDEX] - assert isinstance(w_v, model.W_PointersObject) - return w_v - - def store_w_lastlink(self, w_object): - self.w_self()._vars[constants.LAST_LINK_INDEX] = w_object - - def is_empty_list(self): - from pypy.lang.smalltalk import objtable - return self.w_firstlink() == objtable.w_nil - - def add_last_link(self, w_object): - if self.is_empty_list(): - self.store_w_firstlink(w_object) - else: - self.w_lastlink().as_link_get_shadow().store_next(w_object) - # XXX Slang version stores list in process here... - self.store_w_lastlink(w_object) - - def remove_first_link_of_list(self): - from pypy.lang.smalltalk import objtable - first = self.w_firstlink() - last = self.w_lastlink() - if first == last: - self.store_w_firstlink(objtable.w_nil) - self.store_w_lastlink(objtable.w_nil) - else: - next = first.as_process_get_shadow().next() - self.store_w_firstlink(next) - first.as_process_get_shadow().store_next(objtable.w_nil) - return first - -class SemaphoreShadow(LinkedListShadow): - """A shadow for Smalltalk objects that are semaphores - """ - def __init__(self, w_self, invalid=False): - LinkedListShadow.__init__(self, w_self, invalid) - - def put_to_sleep(self, s_process): - priority = s_process.priority() - s_scheduler = self.s_scheduler() - w_process_lists = s_scheduler.process_lists() - w_process_list = w_process_lists._vars[priority] - assert isinstance(w_process_list, model.W_PointersObject) - w_process_list.as_linkedlist_get_shadow().add_last_link(s_process.w_self()) - s_process.store_my_list(w_process_list) - - def transfer_to(self, s_process, interp): - from pypy.lang.smalltalk import objtable - s_scheduler = self.s_scheduler() - s_old_process = s_scheduler.s_active_process() - s_scheduler.store_w_active_process(s_process.w_self()) - s_old_process.store_w_suspended_context(interp.s_active_context().w_self()) - interp.store_w_active_context(s_process.w_suspended_context()) - s_process.store_w_suspended_context(objtable.w_nil) - #reclaimableContextCount := 0 - - def s_scheduler(self): - from pypy.lang.smalltalk import objtable - w_association = objtable.objtable["w_schedulerassociationpointer"] - assert w_association is not None - assert isinstance(w_association, model.W_PointersObject) - w_scheduler = w_association.as_association_get_shadow().value() - assert isinstance(w_scheduler, model.W_PointersObject) - return w_scheduler.as_scheduler_get_shadow() - - def resume(self, w_process, interp): - s_process = w_process.as_process_get_shadow() - s_scheduler = self.s_scheduler() - s_active_process = s_scheduler.s_active_process() - active_priority = s_active_process.priority() - new_priority = s_process.priority() - if new_priority > active_priority: - self.put_to_sleep(s_active_process) - self.transfer_to(s_process, interp) - else: - self.put_to_sleep(s_process) - - def synchronous_signal(self, interp): - if self.is_empty_list(): - w_value = self.w_self()._vars[constants.EXCESS_SIGNALS_INDEX] - w_value = utility.wrap_int(utility.unwrap_int(w_value) + 1) - self.w_self()._vars[constants.EXCESS_SIGNALS_INDEX] = w_value - else: - self.resume(self.remove_first_link_of_list(), interp) - -class LinkShadow(AbstractShadow): - def __init__(self, w_self, invalid): - AbstractShadow.__init__(self, w_self, invalid) - - def next(self): - return self.w_self()._vars[constants.NEXT_LINK_INDEX] - - def store_next(self, w_object): - self.w_self()._vars[constants.NEXT_LINK_INDEX] = w_object - -class ProcessShadow(LinkShadow): - """A shadow for Smalltalk objects that are processes - """ - def __init__(self, w_self, invalid): - LinkShadow.__init__(self, w_self, invalid) - - def priority(self): - return utility.unwrap_int(self.w_self()._vars[constants.PROCESS_PRIORITY_INDEX]) - - def my_list(self): - return self.w_self()._vars[constants.PROCESS_MY_LIST_INDEX] - - def store_my_list(self, w_object): - self.w_self()._vars[constants.PROCESS_MY_LIST_INDEX] = w_object - - def w_suspended_context(self): - # XXX Can currently only restart context if it is a method context... - # XXX Depends on typechecking ... - return self.w_self()._vars[constants.PROCESS_SUSPENDED_CONTEXT_INDEX] - - def store_w_suspended_context(self, w_object): - self.w_self()._vars[constants.PROCESS_SUSPENDED_CONTEXT_INDEX] = w_object - -class AssociationShadow(AbstractShadow): - def __init__(self, w_self, invalid): - AbstractShadow.__init__(self, w_self, invalid) - - def key(self): - return self.w_self()._vars[constants.ASSOCIATION_KEY_INDEX] - - def value(self): - return self.w_self()._vars[constants.ASSOCIATION_VALUE_INDEX] - - def store_value(self, w_value): - self.w_self()._vars[constants.ASSOCIATION_VALUE_INDEX] = w_value - -class SchedulerShadow(AbstractShadow): - def __init__(self, w_self, invalid): - AbstractShadow.__init__(self, w_self, invalid) - - def s_active_process(self): - w_v = self.w_self()._vars[constants.SCHEDULER_ACTIVE_PROCESS_INDEX] - assert isinstance(w_v, model.W_PointersObject) - return w_v.as_process_get_shadow() - - def store_w_active_process(self, w_object): - self.w_self()._vars[constants.SCHEDULER_ACTIVE_PROCESS_INDEX] = w_object - - def process_lists(self): - w_v = self.w_self()._vars[constants.SCHEDULER_PROCESS_LISTS_INDEX] - assert isinstance(w_v, model.W_PointersObject) - return w_v - class ContextPartShadow(AbstractShadow): __metaclass__ = extendabletype Added: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/wrapper.py ============================================================================== --- (empty file) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/wrapper.py Sat May 17 12:05:07 2008 @@ -0,0 +1,185 @@ +from pypy.lang.smalltalk import model + +class Wrapper(object): + def __init__(self, w_self): + assert isinstance(w_self, model.W_PointersObject) + self.w_self = w_self + + def read(self, index0): + try: + return self.w_self._vars[index0] + except IndexError: + # XXX nicer errormessage + raise + + def write(self, index0, w_new): + try: + self.w_self._vars[index0] = w_new + except IndexError: + # XXX nicer errormessage + raise + + +'''class LinkedListShadow(AbstractShadow): + def __init__(self, w_self, invalid): + AbstractShadow.__init__(self, w_self, invalid) + + def w_firstlink(self): + w_v = self.w_self()._vars[constants.FIRST_LINK_INDEX] + assert isinstance(w_v, model.W_PointersObject) + return w_v + + def store_w_firstlink(self, w_object): + self.w_self()._vars[constants.FIRST_LINK_INDEX] = w_object + + def w_lastlink(self): + w_v = self.w_self()._vars[constants.LAST_LINK_INDEX] + assert isinstance(w_v, model.W_PointersObject) + return w_v + + def store_w_lastlink(self, w_object): + self.w_self()._vars[constants.LAST_LINK_INDEX] = w_object + + def is_empty_list(self): + from pypy.lang.smalltalk import objtable + return self.w_firstlink() == objtable.w_nil + + def add_last_link(self, w_object): + if self.is_empty_list(): + self.store_w_firstlink(w_object) + else: + self.w_lastlink().as_link_get_shadow().store_next(w_object) + # XXX Slang version stores list in process here... + self.store_w_lastlink(w_object) + + def remove_first_link_of_list(self): + from pypy.lang.smalltalk import objtable + first = self.w_firstlink() + last = self.w_lastlink() + if first == last: + self.store_w_firstlink(objtable.w_nil) + self.store_w_lastlink(objtable.w_nil) + else: + next = first.as_process_get_shadow().next() + self.store_w_firstlink(next) + first.as_process_get_shadow().store_next(objtable.w_nil) + return first + +class SemaphoreShadow(LinkedListShadow): + """A shadow for Smalltalk objects that are semaphores + """ + def __init__(self, w_self, invalid=False): + LinkedListShadow.__init__(self, w_self, invalid) + + def put_to_sleep(self, s_process): + priority = s_process.priority() + s_scheduler = self.s_scheduler() + w_process_lists = s_scheduler.process_lists() + w_process_list = w_process_lists._vars[priority] + assert isinstance(w_process_list, model.W_PointersObject) + w_process_list.as_linkedlist_get_shadow().add_last_link(s_process.w_self()) + s_process.store_my_list(w_process_list) + + def transfer_to(self, s_process, interp): + from pypy.lang.smalltalk import objtable + s_scheduler = self.s_scheduler() + s_old_process = s_scheduler.s_active_process() + s_scheduler.store_w_active_process(s_process.w_self()) + s_old_process.store_w_suspended_context(interp.s_active_context().w_self()) + interp.store_w_active_context(s_process.w_suspended_context()) + s_process.store_w_suspended_context(objtable.w_nil) + #reclaimableContextCount := 0 + + def s_scheduler(self): + from pypy.lang.smalltalk import objtable + w_association = objtable.objtable["w_schedulerassociationpointer"] + assert w_association is not None + assert isinstance(w_association, model.W_PointersObject) + w_scheduler = w_association.as_association_get_shadow().value() + assert isinstance(w_scheduler, model.W_PointersObject) + return w_scheduler.as_scheduler_get_shadow() + + def resume(self, w_process, interp): + s_process = w_process.as_process_get_shadow() + s_scheduler = self.s_scheduler() + s_active_process = s_scheduler.s_active_process() + active_priority = s_active_process.priority() + new_priority = s_process.priority() + if new_priority > active_priority: + self.put_to_sleep(s_active_process) + self.transfer_to(s_process, interp) + else: + self.put_to_sleep(s_process) + + def synchronous_signal(self, interp): + if self.is_empty_list(): + w_value = self.w_self()._vars[constants.EXCESS_SIGNALS_INDEX] + w_value = utility.wrap_int(utility.unwrap_int(w_value) + 1) + self.w_self()._vars[constants.EXCESS_SIGNALS_INDEX] = w_value + else: + self.resume(self.remove_first_link_of_list(), interp) + +class LinkShadow(AbstractShadow): + def __init__(self, w_self, invalid): + AbstractShadow.__init__(self, w_self, invalid) + + def next(self): + return self.w_self()._vars[constants.NEXT_LINK_INDEX] + + def store_next(self, w_object): + self.w_self()._vars[constants.NEXT_LINK_INDEX] = w_object + +class ProcessShadow(LinkShadow): + """A shadow for Smalltalk objects that are processes + """ + def __init__(self, w_self, invalid): + LinkShadow.__init__(self, w_self, invalid) + + def priority(self): + return utility.unwrap_int(self.w_self()._vars[constants.PROCESS_PRIORITY_INDEX]) + + def my_list(self): + return self.w_self()._vars[constants.PROCESS_MY_LIST_INDEX] + + def store_my_list(self, w_object): + self.w_self()._vars[constants.PROCESS_MY_LIST_INDEX] = w_object + + def w_suspended_context(self): + # XXX Can currently only restart context if it is a method context... + # XXX Depends on typechecking ... + return self.w_self()._vars[constants.PROCESS_SUSPENDED_CONTEXT_INDEX] + + def store_w_suspended_context(self, w_object): + self.w_self()._vars[constants.PROCESS_SUSPENDED_CONTEXT_INDEX] = w_object + +class AssociationShadow(AbstractShadow): + def __init__(self, w_self, invalid): + AbstractShadow.__init__(self, w_self, invalid) + + def key(self): + return self.w_self()._vars[constants.ASSOCIATION_KEY_INDEX] + + def value(self): + return self.w_self()._vars[constants.ASSOCIATION_VALUE_INDEX] + + def store_value(self, w_value): + self.w_self()._vars[constants.ASSOCIATION_VALUE_INDEX] = w_value + +class SchedulerShadow(AbstractShadow): + def __init__(self, w_self, invalid): + AbstractShadow.__init__(self, w_self, invalid) + + def s_active_process(self): + w_v = self.w_self()._vars[constants.SCHEDULER_ACTIVE_PROCESS_INDEX] + assert isinstance(w_v, model.W_PointersObject) + return w_v.as_process_get_shadow() + + def store_w_active_process(self, w_object): + self.w_self()._vars[constants.SCHEDULER_ACTIVE_PROCESS_INDEX] = w_object + + def process_lists(self): + w_v = self.w_self()._vars[constants.SCHEDULER_PROCESS_LISTS_INDEX] + assert isinstance(w_v, model.W_PointersObject) + return w_v + +''' From fijal at codespeak.net Sat May 17 12:13:11 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 17 May 2008 12:13:11 +0200 (CEST) Subject: [pypy-svn] r54812 - pypy/dist/pypy/rlib Message-ID: <20080517101311.32704168548@codespeak.net> Author: fijal Date: Sat May 17 12:13:10 2008 New Revision: 54812 Modified: pypy/dist/pypy/rlib/libffi.py Log: I'm not sure what this is supposed to do, but sometimes it simply says "False" while everything is fine. Modified: pypy/dist/pypy/rlib/libffi.py ============================================================================== --- pypy/dist/pypy/rlib/libffi.py (original) +++ pypy/dist/pypy/rlib/libffi.py Sat May 17 12:13:10 2008 @@ -47,9 +47,6 @@ ], export_symbols = ['ffi_call', 'ffi_prep_cif', 'ffi_prep_closure'], ) - -if not rffi_platform.check_eci(eci): - raise ImportError("cannot find an installed 'libffi' library") FFI_TYPE_P = lltype.Ptr(lltype.ForwardReference()) FFI_TYPE_PP = rffi.CArrayPtr(FFI_TYPE_P) From fijal at codespeak.net Sat May 17 12:23:33 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 17 May 2008 12:23:33 +0200 (CEST) Subject: [pypy-svn] r54814 - pypy/dist/pypy/module/_rawffi Message-ID: <20080517102333.7623F168518@codespeak.net> Author: fijal Date: Sat May 17 12:23:32 2008 New Revision: 54814 Modified: pypy/dist/pypy/module/_rawffi/interp_rawffi.py Log: (fijal, felix) Fix linux support Modified: pypy/dist/pypy/module/_rawffi/interp_rawffi.py ============================================================================== --- pypy/dist/pypy/module/_rawffi/interp_rawffi.py (original) +++ pypy/dist/pypy/module/_rawffi/interp_rawffi.py Sat May 17 12:23:32 2008 @@ -9,10 +9,10 @@ from pypy.rpython.lltypesystem import lltype, rffi from pypy.rlib.unroll import unrolling_iterable -try: +_MS_WINDOWS = os.name == "nt" + +if _MS_WINDOWS: from pypy.rlib import rwin32 -except: - rwin32 = None from pypy.tool.sourcetools import func_with_new_name from pypy.rlib.rarithmetic import intmask, r_uint, r_singlefloat @@ -458,12 +458,13 @@ return space.wrap(s) charp2rawstring.unwrap_spec = [ObjSpace, r_uint, int] -def FormatError(space, code): - return space.wrap(rwin32.FormatError(code)) -FormatError.unwrap_spec = [ObjSpace, int] - -def check_HRESULT(space, hresult): - if rwin32.FAILED(hresult): - raise OperationError(space.w_WindowsError, space.wrap(hresult)) - return space.wrap(hresult) -check_HRESULT.unwrap_spec = [ObjSpace, int] +if _MS_WINDOWS: + def FormatError(space, code): + return space.wrap(rwin32.FormatError(code)) + FormatError.unwrap_spec = [ObjSpace, int] + + def check_HRESULT(space, hresult): + if rwin32.FAILED(hresult): + raise OperationError(space.w_WindowsError, space.wrap(hresult)) + return space.wrap(hresult) + check_HRESULT.unwrap_spec = [ObjSpace, int] From arigo at codespeak.net Sat May 17 12:31:36 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 17 May 2008 12:31:36 +0200 (CEST) Subject: [pypy-svn] r54815 - in pypy/dist/pypy/rlib/rsdl: . test Message-ID: <20080517103136.D7CB8168554@codespeak.net> Author: arigo Date: Sat May 17 12:31:35 2008 New Revision: 54815 Modified: pypy/dist/pypy/rlib/rsdl/RSDL.py pypy/dist/pypy/rlib/rsdl/test/test_basic.py Log: (karlb, cami, arigo) SetVideoMode works. Modified: pypy/dist/pypy/rlib/rsdl/RSDL.py ============================================================================== --- pypy/dist/pypy/rlib/rsdl/RSDL.py (original) +++ pypy/dist/pypy/rlib/rsdl/RSDL.py Sat May 17 12:31:35 2008 @@ -18,8 +18,13 @@ INIT_VIDEO = platform.ConstantInteger('SDL_INIT_VIDEO') + Surface = platform.Struct('SDL_Surface', []) + globals().update(platform.configure(CConfig)) Init = external('SDL_Init', [Uint32], rffi.INT) Quit = external('SDL_Quit', [], lltype.Void) +SetVideoMode = external('SDL_SetVideoMode', [rffi.INT, rffi.INT, + rffi.INT, Uint32], + lltype.Ptr(Surface)) Modified: pypy/dist/pypy/rlib/rsdl/test/test_basic.py ============================================================================== --- pypy/dist/pypy/rlib/rsdl/test/test_basic.py (original) +++ pypy/dist/pypy/rlib/rsdl/test/test_basic.py Sat May 17 12:31:35 2008 @@ -5,3 +5,9 @@ def test_sdl_init(): assert RSDL.Init(RSDL.INIT_VIDEO) >= 0 RSDL.Quit() + +def test_set_video_mode(): + assert RSDL.Init(RSDL.INIT_VIDEO) >= 0 + surface = RSDL.SetVideoMode(640, 480, 32, 0) + assert surface + RSDL.Quit() From antocuni at codespeak.net Sat May 17 12:34:32 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Sat, 17 May 2008 12:34:32 +0200 (CEST) Subject: [pypy-svn] r54816 - in pypy/branch/oo-jit/pypy: annotation rpython/test Message-ID: <20080517103432.8190E2A0185@codespeak.net> Author: antocuni Date: Sat May 17 12:34:31 2008 New Revision: 54816 Modified: pypy/branch/oo-jit/pypy/annotation/binaryop.py pypy/branch/oo-jit/pypy/annotation/builtin.py pypy/branch/oo-jit/pypy/rpython/test/test_rclass.py Log: teach the annotator how to do union(SomeOOObject, SomeOOObject) Modified: pypy/branch/oo-jit/pypy/annotation/binaryop.py ============================================================================== --- pypy/branch/oo-jit/pypy/annotation/binaryop.py (original) +++ pypy/branch/oo-jit/pypy/annotation/binaryop.py Sat May 17 12:34:31 2008 @@ -894,6 +894,7 @@ # ____________________________________________________________ # annotation of low-level types from pypy.annotation.model import SomePtr, SomeOOInstance, SomeOOClass +from pypy.annotation.model import SomeOOObject from pypy.annotation.model import ll_to_annotation, annotation_to_lltype from pypy.rpython.ootypesystem import ootype @@ -964,6 +965,10 @@ def union((obj, r2)): return pair(r2, obj).union() +class __extend__(pairtype(SomeOOObject, SomeOOObject)): + def union((r1, r2)): + assert r1.ootype is ootype.Object and r2.ootype is ootype.Object + return SomeOOObject() #_________________________________________ # weakrefs Modified: pypy/branch/oo-jit/pypy/annotation/builtin.py ============================================================================== --- pypy/branch/oo-jit/pypy/annotation/builtin.py (original) +++ pypy/branch/oo-jit/pypy/annotation/builtin.py Sat May 17 12:34:31 2008 @@ -574,7 +574,9 @@ def cast_from_object(T, obj): TYPE = T.const - if isinstance(TYPE, ootype.Instance): + if TYPE is ootype.Object: + return T + elif isinstance(TYPE, ootype.Instance): return SomeOOInstance(TYPE) elif isinstance(TYPE, ootype.Record): return SomeOOInstance(TYPE) # XXX: SomeOORecord? Modified: pypy/branch/oo-jit/pypy/rpython/test/test_rclass.py ============================================================================== --- pypy/branch/oo-jit/pypy/rpython/test/test_rclass.py (original) +++ pypy/branch/oo-jit/pypy/rpython/test/test_rclass.py Sat May 17 12:34:31 2008 @@ -811,9 +811,8 @@ assert destrb is not None assert destra is not None - def test_cast_object(self): + def test_cast_object_instance(self): A = ootype.Instance("Foo", ootype.ROOT) - B = ootype.Record({'x': ootype.Signed}) def fn_instance(): a = ootype.new(A) @@ -824,6 +823,9 @@ assert a is a3 self.interpret(fn_instance, []) + def test_cast_object_record(self): + B = ootype.Record({'x': ootype.Signed}) + def fn_record(): b = ootype.new(B) b.x = 42 @@ -832,7 +834,11 @@ assert b2.x == 42 assert b is b2 self.interpret(fn_record, []) - + + def test_cast_object_null(self): + A = ootype.Instance("Foo", ootype.ROOT) + B = ootype.Record({'x': ootype.Signed}) + def fn_null(): a = ootype.null(A) b = ootype.null(B) @@ -843,6 +849,8 @@ assert ootype.cast_from_object(B, obj2) == b self.interpret(fn_null, []) + def test_cast_object_is_true(self): + A = ootype.Instance("Foo", ootype.ROOT) def fn_is_true(flag): if flag: a = ootype.new(A) @@ -852,3 +860,15 @@ return bool(obj) assert self.interpret(fn_is_true, [True]) is True assert self.interpret(fn_is_true, [False]) is False + + def test_cast_object_mix_null(self): + A = ootype.Instance("Foo", ootype.ROOT) + def fn_mix_null(flag): + a = ootype.new(A) + obj = ootype.cast_to_object(a) + if flag: + return obj + else: + return ootype.NULL + res = self.interpret(fn_mix_null, [False]) + assert res is ootype.NULL From arigo at codespeak.net Sat May 17 12:51:02 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 17 May 2008 12:51:02 +0200 (CEST) Subject: [pypy-svn] r54817 - in pypy/dist/pypy/rlib/rsdl: . test Message-ID: <20080517105102.5F52A168549@codespeak.net> Author: arigo Date: Sat May 17 12:51:01 2008 New Revision: 54817 Modified: pypy/dist/pypy/rlib/rsdl/RSDL.py pypy/dist/pypy/rlib/rsdl/test/test_basic.py Log: (karlb, cami, arigo) Basic support for creating and inspecting surfaces. Modified: pypy/dist/pypy/rlib/rsdl/RSDL.py ============================================================================== --- pypy/dist/pypy/rlib/rsdl/RSDL.py (original) +++ pypy/dist/pypy/rlib/rsdl/RSDL.py Sat May 17 12:51:01 2008 @@ -18,7 +18,8 @@ INIT_VIDEO = platform.ConstantInteger('SDL_INIT_VIDEO') - Surface = platform.Struct('SDL_Surface', []) + Surface = platform.Struct('SDL_Surface', [('w', rffi.INT), + ('h', rffi.INT)]) globals().update(platform.configure(CConfig)) @@ -28,3 +29,9 @@ SetVideoMode = external('SDL_SetVideoMode', [rffi.INT, rffi.INT, rffi.INT, Uint32], lltype.Ptr(Surface)) +CreateRGBSurface = external('SDL_CreateRGBSurface', [Uint32, rffi.INT, + rffi.INT, rffi.INT, + Uint32, Uint32, + Uint32, Uint32], + lltype.Ptr(Surface)) +FreeSurface = external('SDL_FreeSurface', [lltype.Ptr(Surface)], lltype.Void) Modified: pypy/dist/pypy/rlib/rsdl/test/test_basic.py ============================================================================== --- pypy/dist/pypy/rlib/rsdl/test/test_basic.py (original) +++ pypy/dist/pypy/rlib/rsdl/test/test_basic.py Sat May 17 12:51:01 2008 @@ -1,5 +1,7 @@ import py from pypy.rlib.rsdl import RSDL +from pypy.rlib.rarithmetic import r_uint +from pypy.rpython.lltypesystem import rffi def test_sdl_init(): @@ -11,3 +13,16 @@ surface = RSDL.SetVideoMode(640, 480, 32, 0) assert surface RSDL.Quit() + +def test_surface_basic(): + assert RSDL.Init(RSDL.INIT_VIDEO) >= 0 + surface = RSDL.CreateRGBSurface(0, 150, 50, 32, + r_uint(0x000000FF), + r_uint(0x0000FF00), + r_uint(0x00FF0000), + r_uint(0xFF000000)) + assert surface + assert rffi.getintfield(surface, 'c_w') == 150 + assert rffi.getintfield(surface, 'c_h') == 50 + RSDL.FreeSurface(surface) + RSDL.Quit() From arigo at codespeak.net Sat May 17 13:16:57 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 17 May 2008 13:16:57 +0200 (CEST) Subject: [pypy-svn] r54818 - in pypy/dist/pypy/translator/tool: . test Message-ID: <20080517111657.7577E168571@codespeak.net> Author: arigo Date: Sat May 17 13:16:55 2008 New Revision: 54818 Modified: pypy/dist/pypy/translator/tool/cbuild.py pypy/dist/pypy/translator/tool/test/test_cbuild.py Log: Some libraries have tools "xxx-config" that can be run to get compiler paths and libraries information. Add support for that in ExternalCompilationInfo. Modified: pypy/dist/pypy/translator/tool/cbuild.py ============================================================================== --- pypy/dist/pypy/translator/tool/cbuild.py (original) +++ pypy/dist/pypy/translator/tool/cbuild.py Sat May 17 13:16:55 2008 @@ -65,6 +65,38 @@ assert isinstance(value, (list, tuple)) setattr(self, name, tuple(value)) + def from_compiler_flags(cls, flags): + """Returns a new ExternalCompilationInfo instance by parsing + the string 'flags', which is in the typical Unix compiler flags + format.""" + pre_include_lines = [] + include_dirs = [] + libraries = [] + library_dirs = [] + for arg in flags.split(): + if arg.startswith('-I'): + include_dirs.append(arg[2:]) + elif arg.startswith('-L'): + library_dirs.append(arg[2:]) + elif arg.startswith('-l'): + libraries.append(arg[2:]) + elif arg.startswith('-D'): + pre_include_lines.append('#define ' + arg[2:]) + return cls(pre_include_lines=pre_include_lines, + include_dirs=include_dirs, + libraries=libraries, + library_dirs=library_dirs) + from_compiler_flags = classmethod(from_compiler_flags) + + def from_config_tool(cls, execonfigtool): + """Returns a new ExternalCompilationInfo instance by executing + the 'execonfigtool' with --cflags and --libs arguments.""" + execonfigtool = str(execonfigtool) + cflags = py.process.cmdexec([execonfigtool, '--cflags']) + libs = py.process.cmdexec([execonfigtool, '--libs']) + return cls.from_compiler_flags(cflags + ' ' + libs) + from_config_tool = classmethod(from_config_tool) + def _value(self): return tuple([getattr(self, x) for x in self._ATTRIBUTES]) Modified: pypy/dist/pypy/translator/tool/test/test_cbuild.py ============================================================================== --- pypy/dist/pypy/translator/tool/test/test_cbuild.py (original) +++ pypy/dist/pypy/translator/tool/test/test_cbuild.py Sat May 17 13:16:55 2008 @@ -124,3 +124,27 @@ assert ctypes.CDLL(neweci.libraries[0]).get() == 42 assert not neweci.separate_module_sources assert not neweci.separate_module_files + + def test_from_compiler_flags(self): + flags = ('-I/some/include/path -L/some/lib/path ' + '-I/other/include/path -L/other/lib/path ' + '-lmylib1 -lmylib2 ' + '-DMACRO1 -D_MACRO2') + eci = ExternalCompilationInfo.from_compiler_flags(flags) + assert eci.pre_include_lines == ('#define MACRO1', + '#define _MACRO2') + assert eci.includes == () + assert eci.include_dirs == ('/some/include/path', + '/other/include/path') + assert eci.libraries == ('mylib1', 'mylib2') + assert eci.library_dirs == ('/some/lib/path', + '/other/lib/path') + + def test_from_config_tool(self): + sdlconfig = py.path.local.sysfind('sdl-config') + if not sdlconfig: + py.test.skip("sdl-config not installed") + eci = ExternalCompilationInfo.from_config_tool(sdlconfig) + assert 'SDL' in eci.libraries + eci2 = ExternalCompilationInfo.from_config_tool(str(sdlconfig)) + assert eci2 == eci From arigo at codespeak.net Sat May 17 13:19:02 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 17 May 2008 13:19:02 +0200 (CEST) Subject: [pypy-svn] r54819 - pypy/dist/pypy/rlib/rsdl Message-ID: <20080517111902.1D331168573@codespeak.net> Author: arigo Date: Sat May 17 13:19:01 2008 New Revision: 54819 Modified: pypy/dist/pypy/rlib/rsdl/RSDL.py Log: Use ExternalCompilationInfo.from_config_tool() in rsdl. Modified: pypy/dist/pypy/rlib/rsdl/RSDL.py ============================================================================== --- pypy/dist/pypy/rlib/rsdl/RSDL.py (original) +++ pypy/dist/pypy/rlib/rsdl/RSDL.py Sat May 17 13:19:01 2008 @@ -3,10 +3,9 @@ from pypy.translator.tool.cbuild import ExternalCompilationInfo eci = ExternalCompilationInfo( - includes = ['SDL.h'], - include_dirs = ['/usr/include/SDL'], - libraries = ['SDL'], -) + includes=['SDL.h'], + ) +eci = eci.merge(ExternalCompilationInfo.from_config_tool('sdl-config')) def external(name, args, result): return rffi.llexternal(name, args, result, compilation_info=eci) From arigo at codespeak.net Sat May 17 13:23:15 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 17 May 2008 13:23:15 +0200 (CEST) Subject: [pypy-svn] r54820 - pypy/dist/pypy/rlib/rsdl/test Message-ID: <20080517112315.15CC616853F@codespeak.net> Author: arigo Date: Sat May 17 13:23:15 2008 New Revision: 54820 Modified: pypy/dist/pypy/rlib/rsdl/test/test_basic.py Log: Reorganize tests so that "py.test --view" is needed to run the tests that try to open a window. Modified: pypy/dist/pypy/rlib/rsdl/test/test_basic.py ============================================================================== --- pypy/dist/pypy/rlib/rsdl/test/test_basic.py (original) +++ pypy/dist/pypy/rlib/rsdl/test/test_basic.py Sat May 17 13:23:15 2008 @@ -2,18 +2,13 @@ from pypy.rlib.rsdl import RSDL from pypy.rlib.rarithmetic import r_uint from pypy.rpython.lltypesystem import rffi +from pypy import conftest def test_sdl_init(): assert RSDL.Init(RSDL.INIT_VIDEO) >= 0 RSDL.Quit() -def test_set_video_mode(): - assert RSDL.Init(RSDL.INIT_VIDEO) >= 0 - surface = RSDL.SetVideoMode(640, 480, 32, 0) - assert surface - RSDL.Quit() - def test_surface_basic(): assert RSDL.Init(RSDL.INIT_VIDEO) >= 0 surface = RSDL.CreateRGBSurface(0, 150, 50, 32, @@ -26,3 +21,20 @@ assert rffi.getintfield(surface, 'c_h') == 50 RSDL.FreeSurface(surface) RSDL.Quit() + + +class TestVideo: + + def setup_method(self, meth): + if not conftest.option.view: + py.test.skip("'--view' not specified, " + "skipping tests that open a window") + assert RSDL.Init(RSDL.INIT_VIDEO) >= 0 + self.surface = RSDL.SetVideoMode(640, 480, 32, 0) + assert self.surface + + def test_simple(self): + pass # only checks that opening and closing the window works + + def teardown_method(self, meth): + RSDL.Quit() From arigo at codespeak.net Sat May 17 15:06:09 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 17 May 2008 15:06:09 +0200 (CEST) Subject: [pypy-svn] r54824 - in pypy/dist/pypy/translator/tool: . test Message-ID: <20080517130609.5AD8716854A@codespeak.net> Author: arigo Date: Sat May 17 15:06:05 2008 New Revision: 54824 Modified: pypy/dist/pypy/translator/tool/cbuild.py pypy/dist/pypy/translator/tool/test/test_cbuild.py Log: Polishing. Modified: pypy/dist/pypy/translator/tool/cbuild.py ============================================================================== --- pypy/dist/pypy/translator/tool/cbuild.py (original) +++ pypy/dist/pypy/translator/tool/cbuild.py Sat May 17 15:06:05 2008 @@ -91,9 +91,13 @@ def from_config_tool(cls, execonfigtool): """Returns a new ExternalCompilationInfo instance by executing the 'execonfigtool' with --cflags and --libs arguments.""" - execonfigtool = str(execonfigtool) - cflags = py.process.cmdexec([execonfigtool, '--cflags']) - libs = py.process.cmdexec([execonfigtool, '--libs']) + path = py.path.local.sysfind(execonfigtool) + if not path: + raise ImportError("cannot find %r" % (execonfigtool,)) + # we raise ImportError to be nice to the pypy.config.pypyoption + # logic of skipping modules depending on non-installed libs + cflags = py.process.cmdexec([str(path), '--cflags']) + libs = py.process.cmdexec([str(path), '--libs']) return cls.from_compiler_flags(cflags + ' ' + libs) from_config_tool = classmethod(from_config_tool) Modified: pypy/dist/pypy/translator/tool/test/test_cbuild.py ============================================================================== --- pypy/dist/pypy/translator/tool/test/test_cbuild.py (original) +++ pypy/dist/pypy/translator/tool/test/test_cbuild.py Sat May 17 15:06:05 2008 @@ -144,7 +144,10 @@ sdlconfig = py.path.local.sysfind('sdl-config') if not sdlconfig: py.test.skip("sdl-config not installed") - eci = ExternalCompilationInfo.from_config_tool(sdlconfig) + eci = ExternalCompilationInfo.from_config_tool('sdl-config') assert 'SDL' in eci.libraries - eci2 = ExternalCompilationInfo.from_config_tool(str(sdlconfig)) - assert eci2 == eci + + def test_from_missing_config_tool(self): + py.test.raises(ImportError, + ExternalCompilationInfo.from_config_tool, + 'dxowqbncpqympqhe-config') From arigo at codespeak.net Sat May 17 15:28:21 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 17 May 2008 15:28:21 +0200 (CEST) Subject: [pypy-svn] r54827 - in pypy/dist/pypy/translator/tool: . test Message-ID: <20080517132821.5C85216855D@codespeak.net> Author: arigo Date: Sat May 17 15:28:20 2008 New Revision: 54827 Modified: pypy/dist/pypy/translator/tool/cbuild.py pypy/dist/pypy/translator/tool/test/test_cbuild.py Log: The commandline option -DFOO really maps to "#define FOO 1". Modified: pypy/dist/pypy/translator/tool/cbuild.py ============================================================================== --- pypy/dist/pypy/translator/tool/cbuild.py (original) +++ pypy/dist/pypy/translator/tool/cbuild.py Sat May 17 15:28:20 2008 @@ -81,7 +81,7 @@ elif arg.startswith('-l'): libraries.append(arg[2:]) elif arg.startswith('-D'): - pre_include_lines.append('#define ' + arg[2:]) + pre_include_lines.append('#define %s 1' % (arg[2:],)) return cls(pre_include_lines=pre_include_lines, include_dirs=include_dirs, libraries=libraries, Modified: pypy/dist/pypy/translator/tool/test/test_cbuild.py ============================================================================== --- pypy/dist/pypy/translator/tool/test/test_cbuild.py (original) +++ pypy/dist/pypy/translator/tool/test/test_cbuild.py Sat May 17 15:28:20 2008 @@ -131,8 +131,8 @@ '-lmylib1 -lmylib2 ' '-DMACRO1 -D_MACRO2') eci = ExternalCompilationInfo.from_compiler_flags(flags) - assert eci.pre_include_lines == ('#define MACRO1', - '#define _MACRO2') + assert eci.pre_include_lines == ('#define MACRO1 1', + '#define _MACRO2 1') assert eci.includes == () assert eci.include_dirs == ('/some/include/path', '/other/include/path') From arigo at codespeak.net Sat May 17 15:32:23 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 17 May 2008 15:32:23 +0200 (CEST) Subject: [pypy-svn] r54828 - in pypy/dist/pypy/rlib/rsdl: . test Message-ID: <20080517133223.DA096168563@codespeak.net> Author: arigo Date: Sat May 17 15:32:22 2008 New Revision: 54828 Added: pypy/dist/pypy/rlib/rsdl/test/test_video.py - copied, changed from r54824, pypy/dist/pypy/rlib/rsdl/test/test_basic.py Modified: pypy/dist/pypy/rlib/rsdl/RSDL.py pypy/dist/pypy/rlib/rsdl/test/test_basic.py Log: Basic logic to run interactive tests. Some more functions implemented. Modified: pypy/dist/pypy/rlib/rsdl/RSDL.py ============================================================================== --- pypy/dist/pypy/rlib/rsdl/RSDL.py (original) +++ pypy/dist/pypy/rlib/rsdl/RSDL.py Sat May 17 15:32:22 2008 @@ -10,27 +10,46 @@ def external(name, args, result): return rffi.llexternal(name, args, result, compilation_info=eci) +RectPtr = lltype.Ptr(lltype.ForwardReference()) +SurfacePtr = lltype.Ptr(lltype.ForwardReference()) +PixelFormatPtr = lltype.Ptr(lltype.ForwardReference()) + class CConfig: _compilation_info_ = eci + Uint8 = platform.SimpleType('Uint8', rffi.INT) Uint32 = platform.SimpleType('Uint32', rffi.INT) INIT_VIDEO = platform.ConstantInteger('SDL_INIT_VIDEO') + Rect = platform.Struct('SDL_Rect', [('x', rffi.INT), + ('y', rffi.INT), + ('w', rffi.INT), + ('h', rffi.INT)]) Surface = platform.Struct('SDL_Surface', [('w', rffi.INT), - ('h', rffi.INT)]) + ('h', rffi.INT), + ('format', PixelFormatPtr)]) + PixelFormat = platform.Struct('SDL_PixelFormat', []) globals().update(platform.configure(CConfig)) +RectPtr.TO.become(Rect) +SurfacePtr.TO.become(Surface) +PixelFormatPtr.TO.become(PixelFormat) + Init = external('SDL_Init', [Uint32], rffi.INT) Quit = external('SDL_Quit', [], lltype.Void) SetVideoMode = external('SDL_SetVideoMode', [rffi.INT, rffi.INT, rffi.INT, Uint32], - lltype.Ptr(Surface)) + SurfacePtr) +Flip = external('SDL_Flip', [SurfacePtr], rffi.INT) CreateRGBSurface = external('SDL_CreateRGBSurface', [Uint32, rffi.INT, rffi.INT, rffi.INT, Uint32, Uint32, Uint32, Uint32], - lltype.Ptr(Surface)) -FreeSurface = external('SDL_FreeSurface', [lltype.Ptr(Surface)], lltype.Void) + SurfacePtr) +FreeSurface = external('SDL_FreeSurface', [SurfacePtr], lltype.Void) + +MapRGB = external('SDL_MapRGB', [PixelFormatPtr, Uint8, Uint8, Uint8], Uint32) +FillRect = external('SDL_FillRect', [SurfacePtr, RectPtr, Uint32], rffi.INT) Modified: pypy/dist/pypy/rlib/rsdl/test/test_basic.py ============================================================================== --- pypy/dist/pypy/rlib/rsdl/test/test_basic.py (original) +++ pypy/dist/pypy/rlib/rsdl/test/test_basic.py Sat May 17 15:32:22 2008 @@ -2,7 +2,6 @@ from pypy.rlib.rsdl import RSDL from pypy.rlib.rarithmetic import r_uint from pypy.rpython.lltypesystem import rffi -from pypy import conftest def test_sdl_init(): @@ -21,20 +20,3 @@ assert rffi.getintfield(surface, 'c_h') == 50 RSDL.FreeSurface(surface) RSDL.Quit() - - -class TestVideo: - - def setup_method(self, meth): - if not conftest.option.view: - py.test.skip("'--view' not specified, " - "skipping tests that open a window") - assert RSDL.Init(RSDL.INIT_VIDEO) >= 0 - self.surface = RSDL.SetVideoMode(640, 480, 32, 0) - assert self.surface - - def test_simple(self): - pass # only checks that opening and closing the window works - - def teardown_method(self, meth): - RSDL.Quit() From arigo at codespeak.net Sat May 17 15:34:53 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 17 May 2008 15:34:53 +0200 (CEST) Subject: [pypy-svn] r54829 - pypy/dist/pypy/rlib/rsdl/test Message-ID: <20080517133453.2D699168567@codespeak.net> Author: arigo Date: Sat May 17 15:34:51 2008 New Revision: 54829 Modified: pypy/dist/pypy/rlib/rsdl/test/test_video.py Log: Comment on how to run this test. Modified: pypy/dist/pypy/rlib/rsdl/test/test_video.py ============================================================================== --- pypy/dist/pypy/rlib/rsdl/test/test_video.py (original) +++ pypy/dist/pypy/rlib/rsdl/test/test_video.py Sat May 17 15:34:51 2008 @@ -4,6 +4,12 @@ from pypy.rpython.lltypesystem import lltype, rffi from pypy import conftest +# +# This test file is skipped unless run with "py.test --view". +# If it is run as "py.test --view -s", then it interactively asks +# for confirmation that the window looks as expected. +# + class TestVideo: From cami at codespeak.net Sat May 17 15:43:35 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Sat, 17 May 2008 15:43:35 +0200 (CEST) Subject: [pypy-svn] r54830 - in pypy/branch/gameboy-emulator/pypy/lang/gameboy: . test Message-ID: <20080517134335.89AB8168569@codespeak.net> Author: cami Date: Sat May 17 15:43:34 2008 New Revision: 54830 Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cartridge.py Log: change battery file write functions to use rlib streams Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py Sat May 17 15:43:34 2008 @@ -3,6 +3,7 @@ from pypy.lang.gameboy import constants from pypy.lang.gameboy.timer import * +from pypy.rlib.streamio import open_file_as_stream import os @@ -28,6 +29,9 @@ +def map_to_byte(value): + return ord(value) & 0xFF + # ============================================================================== # CARTRIDGE @@ -148,35 +152,44 @@ self.load(file) def reset(self): - #self.cartridge_name = None + self.cartridge_name = None self.cartridge_file_path = None - self.cartridge_file = None + self.cartridge_stream = None + self.cartridge_file_contents = None self.battery_name = None self.battery_file_path = None - self.battery_file = None + self.battery_stream = None + self.battery_file_contents = None def load(self, cartridge_path): cartridge_path = str(cartridge_path) self.cartridge_file_path = cartridge_path - #self.cartridge_name = os.path.basename(self.cartridge_file_path) - self.cartridge_file = file(cartridge_path, "r") + self.cartridge_name = os.path.basename(self.cartridge_file_path) + #FIXED open_file_as_stream + self.cartridge_stream = open_file_as_stream(cartridge_path) + self.cartridge_file_contents = map(map_to_byte, \ + self.cartridge_stream.readall()) self.load_battery(cartridge_path) - cartridge_path def load_battery(self, cartridge_file_path): - self.battery_file_path = self.create_battery_file_path(cartridge_path) + self.battery_file_path = self.create_battery_file_path(cartridge_file_path) self.battery_name = os.path.basename(self.battery_file_path) if self.has_battery(): - self.battery_file = open(self.battery_file_path) + self.battery_stream = open_file_as_stream(self.battery_file_path) + self.battery_file_contents = map(map_to_byte, \ + self.battery_stream.readall()) def create_battery_file_path(self, cartridge_file_path): if cartridge_file_path.endswith(constants.CARTRIDGE_FILE_EXTENSION): - return cartridge_file_path.replace(constants.CARTRIDGE_FILE_EXTENSION, - constants.BATTERY_FILE_EXTENSION) - elif cartridge_file_path.endswith(constants.CARTRIDGE_COLOR_FILE_EXTENSION): - return cartridge_file_path.replace(constants.CARTRIDGE_COLOR_FILE_EXTENSION, - constants.BATTERY_FILE_EXTENSION) + return cartridge_file_path.replace( \ + constants.CARTRIDGE_FILE_EXTENSION, + constants.BATTERY_FILE_EXTENSION) + elif cartridge_file_path.endswith(\ + constants.CARTRIDGE_COLOR_FILE_EXTENSION): + return cartridge_file_path.replace( \ + constants.CARTRIDGE_COLOR_FILE_EXTENSION, + constants.BATTERY_FILE_EXTENSION) else: return cartridge_file_path + constants.BATTERY_FILE_EXTENSION @@ -184,17 +197,16 @@ return os.path.exists(self.battery_file_path) def read(self): - self.cartridge_file.seek(0) - return map(map_to_byte, self.cartridge_file.read()) + return self.cartridge_file_contents def read_battery(self): - self.battery_file.seek(0) - return map(map_to_byte, self.battery_file.read()) + return self.battery_file_contents def write_battery(self, ram): - self.battery_file = open(self.battery_file_path, "w") - self.battery_file.write(("").join(map(chr, ram))) - self.battery_file = open(self.battery_file_path, "r+") + output_stream = open_file_as_stream(self.battery_file_path, "w") + output_stream.write(("").join(map(chr, ram))) + output_stream.flush() + self.battery_file_contents = ram def remove_battery(self): if self.has_battery(): @@ -206,11 +218,6 @@ def get_battery_size(self): return os.path.getsize(self.battery_file_path) - - -def map_to_byte(value): - return ord(value) & 0xFF - # ============================================================================== # CARTRIDGE TYPES Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cartridge.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cartridge.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cartridge.py Sat May 17 15:43:34 2008 @@ -10,7 +10,7 @@ ROM_PATH = str(py.magic.autopath().dirpath().dirpath())+"/rom" CONTENT = "abcdefghijklmnopqrstuvwxyz1234567890" -MAPPED_CONTENT = map(mapToByte, CONTENT) +MAPPED_CONTENT = map(map_to_byte, CONTENT) # ------------------------------------------------------------------------------ @@ -43,13 +43,13 @@ def test_cartridge_init(): cartridge = get_cartridge() - #assert cartridge.cartridge_name is None - assert cartridge.cartridge_file_path is None - assert cartridge.cartridge_file is None + assert cartridge.cartridge_name is None + assert cartridge.cartridge_stream is None + assert cartridge.cartridge_file_contents is None assert cartridge.battery_name is None - assert cartridge.battery_file_path is None - assert cartridge.battery_file is None + assert cartridge.battery_stream is None + assert cartridge.battery_file_contents is None def rest_cartridge_load(): @@ -60,12 +60,10 @@ cartridge.load(romFilePath) #assert cartridge.cartridge_name == romName assert cartridge.cartridge_file_path == romFilePath - assert cartridge.cartridge_file is not None assert cartridge.battery_name == romFile+constants.BATTERY_FILE_EXTENSION assert cartridge.battery_file_path == romFilePath+constants.BATTERY_FILE_EXTENSION assert cartridge.has_battery() == False - assert cartridge.battery_file is None def test_cartridge_hasBattery(): @@ -80,9 +78,7 @@ def test_cartridge_read(): cartridge = get_cartridge() - cartridge.cartridge_file = File(CONTENT) - - assert cartridge.read() == MAPPED_CONTENT + assert cartridge.read() == None def test_cartridge_remove_write_read_Battery(): @@ -97,8 +93,6 @@ cartridge.write_battery(MAPPED_CONTENT) assert cartridge.has_battery() == True - print cartridge.battery_file - assert cartridge.battery_file.read() == CONTENT assert cartridge.read_battery() == MAPPED_CONTENT cartridge.remove_battery() From tverwaes at codespeak.net Sat May 17 15:59:51 2008 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Sat, 17 May 2008 15:59:51 +0200 (CEST) Subject: [pypy-svn] r54831 - pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk Message-ID: <20080517135951.7D976168569@codespeak.net> Author: tverwaes Date: Sat May 17 15:59:48 2008 New Revision: 54831 Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/constants.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/wrapper.py Log: moving links to wrapper style Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/constants.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/constants.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/constants.py Sat May 17 15:59:48 2008 @@ -15,9 +15,6 @@ CLASS_FORMAT_INDEX = 2 CLASS_NAME_INDEX = 6 # in the mini.image, at least -# Link -NEXT_LINK_INDEX = 0 - # Process < Link PROCESS_SUSPENDED_CONTEXT_INDEX = 1 PROCESS_PRIORITY_INDEX = 2 Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/wrapper.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/wrapper.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/wrapper.py Sat May 17 15:59:48 2008 @@ -18,7 +18,23 @@ except IndexError: # XXX nicer errormessage raise + +def make_getter(index0): + def getter(self): + return self.read(index0) + return getter + +def make_setter(index0): + def setter(self, w_new): + return self.write(index0, w_new) + return setter + +def make_getter_setter(index0): + return make_getter(index0), make_setter(index0) +class LinkWrapper(Wrapper): + next_link, store_next_link = make_getter_setter(0) + '''class LinkedListShadow(AbstractShadow): def __init__(self, w_self, invalid): @@ -119,39 +135,6 @@ else: self.resume(self.remove_first_link_of_list(), interp) -class LinkShadow(AbstractShadow): - def __init__(self, w_self, invalid): - AbstractShadow.__init__(self, w_self, invalid) - - def next(self): - return self.w_self()._vars[constants.NEXT_LINK_INDEX] - - def store_next(self, w_object): - self.w_self()._vars[constants.NEXT_LINK_INDEX] = w_object - -class ProcessShadow(LinkShadow): - """A shadow for Smalltalk objects that are processes - """ - def __init__(self, w_self, invalid): - LinkShadow.__init__(self, w_self, invalid) - - def priority(self): - return utility.unwrap_int(self.w_self()._vars[constants.PROCESS_PRIORITY_INDEX]) - - def my_list(self): - return self.w_self()._vars[constants.PROCESS_MY_LIST_INDEX] - - def store_my_list(self, w_object): - self.w_self()._vars[constants.PROCESS_MY_LIST_INDEX] = w_object - - def w_suspended_context(self): - # XXX Can currently only restart context if it is a method context... - # XXX Depends on typechecking ... - return self.w_self()._vars[constants.PROCESS_SUSPENDED_CONTEXT_INDEX] - - def store_w_suspended_context(self, w_object): - self.w_self()._vars[constants.PROCESS_SUSPENDED_CONTEXT_INDEX] = w_object - class AssociationShadow(AbstractShadow): def __init__(self, w_self, invalid): AbstractShadow.__init__(self, w_self, invalid) From cami at codespeak.net Sat May 17 16:01:59 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Sat, 17 May 2008 16:01:59 +0200 (CEST) Subject: [pypy-svn] r54832 - pypy/branch/gameboy-emulator/pypy/lang/gameboy/test Message-ID: <20080517140159.11208168569@codespeak.net> Author: cami Date: Sat May 17 16:01:57 2008 New Revision: 54832 Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cartridge.py Log: got rid of the mappint function Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cartridge.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cartridge.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cartridge.py Sat May 17 16:01:57 2008 @@ -10,7 +10,8 @@ ROM_PATH = str(py.magic.autopath().dirpath().dirpath())+"/rom" CONTENT = "abcdefghijklmnopqrstuvwxyz1234567890" -MAPPED_CONTENT = map(map_to_byte, CONTENT) + +MAPPED_CONTENT = map_to_byte(CONTENT) # ------------------------------------------------------------------------------ From karlb at codespeak.net Sat May 17 16:34:23 2008 From: karlb at codespeak.net (karlb at codespeak.net) Date: Sat, 17 May 2008 16:34:23 +0200 (CEST) Subject: [pypy-svn] r54834 - in pypy/dist/pypy: rpython/lltypesystem translator/tool Message-ID: <20080517143423.5406B168557@codespeak.net> Author: karlb Date: Sat May 17 16:34:22 2008 New Revision: 54834 Modified: pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py pypy/dist/pypy/translator/tool/cbuild.py Log: Added MacOS X framework support to cbuild.CCompiler Modified: pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py Sat May 17 16:34:22 2008 @@ -569,7 +569,7 @@ eci = old_eci.compile_shared_lib() _eci_cache[old_eci] = eci - libraries = list(eci.libraries) + libraries = list(eci.libraries + eci.frameworks) FUNCTYPE = lltype.typeOf(funcptr).TO if not libraries: Modified: pypy/dist/pypy/translator/tool/cbuild.py ============================================================================== --- pypy/dist/pypy/translator/tool/cbuild.py (original) +++ pypy/dist/pypy/translator/tool/cbuild.py Sat May 17 16:34:22 2008 @@ -17,7 +17,7 @@ _ATTRIBUTES = ['pre_include_lines', 'includes', 'include_dirs', 'post_include_lines', 'libraries', 'library_dirs', 'separate_module_sources', 'separate_module_files', - 'export_symbols'] + 'export_symbols', 'compile_extra', 'link_extra', 'frameworks'] _AVOID_DUPLICATES = ['separate_module_files', 'libraries', 'includes', 'include_dirs', 'library_dirs', 'separate_module_sources'] @@ -30,7 +30,10 @@ library_dirs = [], separate_module_sources = [], separate_module_files = [], - export_symbols = []): + export_symbols = [], + compile_extra = [], + link_extra = [], + frameworks = []): """ pre_include_lines: list of lines that should be put at the top of the generated .c files, before any #include. They shouldn't @@ -439,11 +442,12 @@ compiler_exe=None, profbased=None): self.cfilenames = cfilenames ext = '' - self.compile_extra = [] - self.link_extra = [] self.libraries = list(eci.libraries) self.include_dirs = list(eci.include_dirs) self.library_dirs = list(eci.library_dirs) + self.compile_extra = list(eci.compile_extra) + self.link_extra = list(eci.link_extra) + self.frameworks = list(eci.frameworks) self.compiler_exe = compiler_exe self.profbased = profbased if not sys.platform in ('win32', 'darwin'): # xxx @@ -465,6 +469,8 @@ os.path.exists(s + 'lib'): self.library_dirs.append(s + 'lib') self.compile_extra += ['-O3', '-fomit-frame-pointer'] + for framework in self.frameworks: + self.link_extra += ['-framework', framework] if outputfilename is None: self.outputfilename = py.path.local(cfilenames[0]).new(ext=ext) @@ -530,6 +536,7 @@ objects.append(str(cobjfile)) finally: old.chdir() + compiler.link_executable(objects, str(self.outputfilename), libraries=self.eci.libraries, extra_preargs=self.link_extra, From tverwaes at codespeak.net Sat May 17 16:36:17 2008 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Sat, 17 May 2008 16:36:17 +0200 (CEST) Subject: [pypy-svn] r54835 - pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test Message-ID: <20080517143617.ADAB116855A@codespeak.net> Author: tverwaes Date: Sat May 17 16:36:16 2008 New Revision: 54835 Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_shadow.py Log: (cfbolz, tverwaes) moving process and linkedlist to wrappers (from shadows) Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_shadow.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_shadow.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_shadow.py Sat May 17 16:36:16 2008 @@ -69,15 +69,6 @@ classshadow = w_class.as_class_get_shadow() assert classshadow.methoddict == methods -def link(w_next='foo'): - w_object = model.W_PointersObject(None, 1) - w_object.store(constants.NEXT_LINK_INDEX, w_next) - return w_object - -def test_link(): - w_object = link() - assert w_object.as_link_get_shadow().next() == 'foo' - def method(tempsize=3,argsize=2, bytes="abcde"): w_m = model.W_CompiledMethod() w_m.bytes = bytes @@ -186,49 +177,21 @@ assert s_object.s_active_process() != w_process.as_process_get_shadow() assert s_object.s_active_process() == w_process2.as_process_get_shadow() -def test_linkedlist(): - w_object = model.W_PointersObject(None,2) - w_last = link(objtable.w_nil) - w_lb1 = link(w_last) - w_lb2 = link(w_lb1) - w_lb3 = link(w_lb2) - w_lb4 = link(w_lb3) - w_first = link(w_lb4) - w_object.store(constants.FIRST_LINK_INDEX, w_first) - w_object.store(constants.LAST_LINK_INDEX, w_last) - s_object = w_object.as_linkedlist_get_shadow() - assert w_first == s_object.w_firstlink() - assert w_last == s_object.w_lastlink() - assert s_object.remove_first_link_of_list() == w_first - assert s_object.remove_first_link_of_list() == w_lb4 - assert s_object.remove_first_link_of_list() == w_lb3 - assert not s_object.is_empty_list() - assert s_object.remove_first_link_of_list() == w_lb2 - assert s_object.remove_first_link_of_list() == w_lb1 - assert s_object.remove_first_link_of_list() == w_last - assert s_object.is_empty_list() - s_object.add_last_link(w_first) - assert s_object.w_firstlink() == w_first - assert s_object.w_lastlink() == w_first - s_object.add_last_link(w_last) - assert s_object.w_firstlink() == w_first - assert s_object.w_lastlink() == w_last - -def test_shadowchanges(): - w_object = model.W_PointersObject(None, 2) - w_o1 = link('a') - w_o2 = link('b') - w_object.store(0, w_o1) - w_object.store(1, w_o2) - s_object = w_object.as_linkedlist_get_shadow() - assert s_object.w_firstlink() == w_o1 - assert s_object.w_lastlink() == w_o2 - assert w_object._shadow == s_object - s_object2 = w_object.as_association_get_shadow() - assert s_object2.key() == w_o1 - assert s_object2.value() == w_o2 - assert w_object._shadow == s_object2 - s_object.sync_shadow() - assert s_object.w_firstlink() == w_o1 - assert s_object.w_lastlink() == w_o2 - assert w_object._shadow == s_object +#def test_shadowchanges(): +# w_object = model.W_PointersObject(None, 2) +# w_o1 = link('a') +# w_o2 = link('b') +# w_object.store(0, w_o1) +# w_object.store(1, w_o2) +# s_object = w_object.as_linkedlist_get_shadow() +# assert s_object.w_firstlink() == w_o1 +# assert s_object.w_lastlink() == w_o2 +# assert w_object._shadow == s_object +# s_object2 = w_object.as_association_get_shadow() +# assert s_object2.key() == w_o1 +# assert s_object2.value() == w_o2 +# assert w_object._shadow == s_object2 +# s_object.sync_shadow() +# assert s_object.w_firstlink() == w_o1 +# assert s_object.w_lastlink() == w_o2 +# assert w_object._shadow == s_object From tverwaes at codespeak.net Sat May 17 16:36:35 2008 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Sat, 17 May 2008 16:36:35 +0200 (CEST) Subject: [pypy-svn] r54836 - pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk Message-ID: <20080517143635.D150516855A@codespeak.net> Author: tverwaes Date: Sat May 17 16:36:34 2008 New Revision: 54836 Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/wrapper.py Log: (cfbolz, tverwaes) belongs to the last commit Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/wrapper.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/wrapper.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/wrapper.py Sat May 17 16:36:34 2008 @@ -35,52 +35,39 @@ class LinkWrapper(Wrapper): next_link, store_next_link = make_getter_setter(0) - -'''class LinkedListShadow(AbstractShadow): - def __init__(self, w_self, invalid): - AbstractShadow.__init__(self, w_self, invalid) - - def w_firstlink(self): - w_v = self.w_self()._vars[constants.FIRST_LINK_INDEX] - assert isinstance(w_v, model.W_PointersObject) - return w_v - - def store_w_firstlink(self, w_object): - self.w_self()._vars[constants.FIRST_LINK_INDEX] = w_object - - def w_lastlink(self): - w_v = self.w_self()._vars[constants.LAST_LINK_INDEX] - assert isinstance(w_v, model.W_PointersObject) - return w_v - - def store_w_lastlink(self, w_object): - self.w_self()._vars[constants.LAST_LINK_INDEX] = w_object +class ProcessWrapper(LinkWrapper): + suspended_context, store_suspended_context = make_getter_setter(1) + priority = make_getter(2) + my_list, store_my_list = make_getter_setter(3) + +class LinkedListWrapper(Wrapper): + first_link, store_first_link = make_getter_setter(0) + last_link, store_last_link = make_getter_setter(1) def is_empty_list(self): from pypy.lang.smalltalk import objtable - return self.w_firstlink() == objtable.w_nil + return self.first_link() is objtable.w_nil def add_last_link(self, w_object): if self.is_empty_list(): - self.store_w_firstlink(w_object) + self.store_first_link(w_object) else: - self.w_lastlink().as_link_get_shadow().store_next(w_object) - # XXX Slang version stores list in process here... - self.store_w_lastlink(w_object) + LinkWrapper(self.last_link()).store_next_link(w_object) + self.store_last_link(w_object) def remove_first_link_of_list(self): from pypy.lang.smalltalk import objtable - first = self.w_firstlink() - last = self.w_lastlink() - if first == last: - self.store_w_firstlink(objtable.w_nil) - self.store_w_lastlink(objtable.w_nil) + w_first = self.first_link() + w_last = self.last_link() + if w_first is w_last: + self.store_first_link(objtable.w_nil) + self.store_last_link(objtable.w_nil) else: - next = first.as_process_get_shadow().next() - self.store_w_firstlink(next) - first.as_process_get_shadow().store_next(objtable.w_nil) - return first - + w_next = LinkWrapper(w_first).next_link() + self.store_first_link(w_next) + LinkWrapper(w_first).store_next_link(objtable.w_nil) + return w_first +''' class SemaphoreShadow(LinkedListShadow): """A shadow for Smalltalk objects that are semaphores """ From arigo at codespeak.net Sat May 17 16:37:45 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 17 May 2008 16:37:45 +0200 (CEST) Subject: [pypy-svn] r54837 - in pypy/dist/pypy/rlib/rsdl: . test Message-ID: <20080517143745.87AB8168557@codespeak.net> Author: arigo Date: Sat May 17 16:37:44 2008 New Revision: 54837 Added: pypy/dist/pypy/rlib/rsdl/RIMG.py (contents, props changed) pypy/dist/pypy/rlib/rsdl/test/autopath.py - copied unchanged from r54824, pypy/dist/pypy/tool/autopath.py pypy/dist/pypy/rlib/rsdl/test/demo.jpg (contents, props changed) pypy/dist/pypy/rlib/rsdl/test/demo.png (contents, props changed) pypy/dist/pypy/rlib/rsdl/test/test_sdl_image.py (contents, props changed) Log: Starting bindings for SDL_image too. Added: pypy/dist/pypy/rlib/rsdl/RIMG.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rlib/rsdl/RIMG.py Sat May 17 16:37:44 2008 @@ -0,0 +1,15 @@ +from pypy.rpython.lltypesystem import lltype, rffi +from pypy.rpython.tool import rffi_platform as platform +from pypy.translator.tool.cbuild import ExternalCompilationInfo +from pypy.rlib.rsdl import RSDL + +eci = ExternalCompilationInfo( + includes=['SDL_image.h'], + libraries=['SDL_image'], + ) +eci = eci.merge(RSDL.eci) + +def external(name, args, result): + return rffi.llexternal(name, args, result, compilation_info=eci) + +Load = external('IMG_Load', [rffi.CCHARP], RSDL.SurfacePtr) Added: pypy/dist/pypy/rlib/rsdl/test/demo.jpg ============================================================================== Binary file. No diff available. Added: pypy/dist/pypy/rlib/rsdl/test/demo.png ============================================================================== Binary file. No diff available. Added: pypy/dist/pypy/rlib/rsdl/test/test_sdl_image.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rlib/rsdl/test/test_sdl_image.py Sat May 17 16:37:44 2008 @@ -0,0 +1,13 @@ +import py, os +import autopath +from pypy.rlib.rsdl import RSDL, RIMG +from pypy.rpython.lltypesystem import rffi + + +def test_load_image(): + for filename in ["demo.jpg", "demo.png"]: + image = RIMG.Load(os.path.join(autopath.this_dir, filename)) + assert image + assert rffi.getintfield(image, 'c_w') == 17 + assert rffi.getintfield(image, 'c_h') == 23 + RSDL.FreeSurface(image) From arigo at codespeak.net Sat May 17 16:42:07 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 17 May 2008 16:42:07 +0200 (CEST) Subject: [pypy-svn] r54838 - in pypy/dist/pypy/translator/tool: . test Message-ID: <20080517144207.6301D16841E@codespeak.net> Author: arigo Date: Sat May 17 16:42:05 2008 New Revision: 54838 Modified: pypy/dist/pypy/translator/tool/cbuild.py pypy/dist/pypy/translator/tool/test/test_cbuild.py Log: Separate from_compiler_flags() and from_linker_flags(). Modified: pypy/dist/pypy/translator/tool/cbuild.py ============================================================================== --- pypy/dist/pypy/translator/tool/cbuild.py (original) +++ pypy/dist/pypy/translator/tool/cbuild.py Sat May 17 16:42:05 2008 @@ -74,23 +74,44 @@ format.""" pre_include_lines = [] include_dirs = [] - libraries = [] - library_dirs = [] + compile_extra = [] for arg in flags.split(): if arg.startswith('-I'): include_dirs.append(arg[2:]) - elif arg.startswith('-L'): - library_dirs.append(arg[2:]) - elif arg.startswith('-l'): - libraries.append(arg[2:]) elif arg.startswith('-D'): pre_include_lines.append('#define %s 1' % (arg[2:],)) + elif arg.startswith('-L') or arg.startswith('-l'): + raise ValueError('linker flag found in compiler options: %r' + % (arg,)) + else: + compile_extra.append(arg) return cls(pre_include_lines=pre_include_lines, include_dirs=include_dirs, - libraries=libraries, - library_dirs=library_dirs) + compile_extra=compile_extra) from_compiler_flags = classmethod(from_compiler_flags) + def from_linker_flags(cls, flags): + """Returns a new ExternalCompilationInfo instance by parsing + the string 'flags', which is in the typical Unix linker flags + format.""" + libraries = [] + library_dirs = [] + link_extra = [] + for arg in flags.split(): + if arg.startswith('-L'): + library_dirs.append(arg[2:]) + elif arg.startswith('-l'): + libraries.append(arg[2:]) + elif arg.startswith('-I') or arg.startswith('-D'): + raise ValueError('compiler flag found in linker options: %r' + % (arg,)) + else: + link_extra.append(arg) + return cls(libraries=libraries, + library_dirs=library_dirs, + link_extra=link_extra) + from_linker_flags = classmethod(from_linker_flags) + def from_config_tool(cls, execonfigtool): """Returns a new ExternalCompilationInfo instance by executing the 'execonfigtool' with --cflags and --libs arguments.""" @@ -100,8 +121,10 @@ # we raise ImportError to be nice to the pypy.config.pypyoption # logic of skipping modules depending on non-installed libs cflags = py.process.cmdexec([str(path), '--cflags']) + eci1 = cls.from_compiler_flags(cflags) libs = py.process.cmdexec([str(path), '--libs']) - return cls.from_compiler_flags(cflags + ' ' + libs) + eci2 = cls.from_linker_flags(libs) + return eci1.merge(eci2) from_config_tool = classmethod(from_config_tool) def _value(self): Modified: pypy/dist/pypy/translator/tool/test/test_cbuild.py ============================================================================== --- pypy/dist/pypy/translator/tool/test/test_cbuild.py (original) +++ pypy/dist/pypy/translator/tool/test/test_cbuild.py Sat May 17 16:42:05 2008 @@ -126,19 +126,24 @@ assert not neweci.separate_module_files def test_from_compiler_flags(self): - flags = ('-I/some/include/path -L/some/lib/path ' - '-I/other/include/path -L/other/lib/path ' - '-lmylib1 -lmylib2 ' - '-DMACRO1 -D_MACRO2') + flags = ('-I/some/include/path -I/other/include/path ' + '-DMACRO1 -D_MACRO2 -?1 -!2') eci = ExternalCompilationInfo.from_compiler_flags(flags) assert eci.pre_include_lines == ('#define MACRO1 1', '#define _MACRO2 1') assert eci.includes == () assert eci.include_dirs == ('/some/include/path', '/other/include/path') + assert eci.compile_extra == ('-?1', '-!2') + + def test_from_linker_flags(self): + flags = ('-L/some/lib/path -L/other/lib/path ' + '-lmylib1 -lmylib2 -?1 -!2') + eci = ExternalCompilationInfo.from_linker_flags(flags) assert eci.libraries == ('mylib1', 'mylib2') assert eci.library_dirs == ('/some/lib/path', '/other/lib/path') + assert eci.link_extra == ('-?1', '-!2') def test_from_config_tool(self): sdlconfig = py.path.local.sysfind('sdl-config') From afa at codespeak.net Sat May 17 16:50:01 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Sat, 17 May 2008 16:50:01 +0200 (CEST) Subject: [pypy-svn] r54839 - pypy/branch/win32port Message-ID: <20080517145001.A4943168560@codespeak.net> Author: afa Date: Sat May 17 16:49:59 2008 New Revision: 54839 Added: pypy/branch/win32port/ - copied from r54838, pypy/dist/pypy/ Log: a branch for win32-related work From karlb at codespeak.net Sat May 17 16:52:08 2008 From: karlb at codespeak.net (karlb at codespeak.net) Date: Sat, 17 May 2008 16:52:08 +0200 (CEST) Subject: [pypy-svn] r54840 - pypy/dist/pypy/rlib/rsdl Message-ID: <20080517145208.E9771168564@codespeak.net> Author: karlb Date: Sat May 17 16:52:07 2008 New Revision: 54840 Modified: pypy/dist/pypy/rlib/rsdl/RSDL.py Log: Added MacOS X Framework support to RSDL Modified: pypy/dist/pypy/rlib/rsdl/RSDL.py ============================================================================== --- pypy/dist/pypy/rlib/rsdl/RSDL.py (original) +++ pypy/dist/pypy/rlib/rsdl/RSDL.py Sat May 17 16:52:07 2008 @@ -1,11 +1,23 @@ from pypy.rpython.lltypesystem import lltype, rffi from pypy.rpython.tool import rffi_platform as platform from pypy.translator.tool.cbuild import ExternalCompilationInfo +import sys -eci = ExternalCompilationInfo( - includes=['SDL.h'], +if sys.platform == 'darwin': + eci = ExternalCompilationInfo( + includes = ['SDL.h'], + include_dirs = ['/Library/Frameworks/SDL.framework/Versions/A/Headers'], + link_extra = [ + '/Users/karl/ctypes-test/SDLMain.m', + '-I', '/Library/Frameworks/SDL.framework/Versions/A/Headers', + ], + frameworks = ['SDL', 'Cocoa'] ) -eci = eci.merge(ExternalCompilationInfo.from_config_tool('sdl-config')) +else: + eci = ExternalCompilationInfo( + includes=['SDL.h'], + ) + eci = eci.merge(ExternalCompilationInfo.from_config_tool('sdl-config')) def external(name, args, result): return rffi.llexternal(name, args, result, compilation_info=eci) @@ -37,8 +49,13 @@ SurfacePtr.TO.become(Surface) PixelFormatPtr.TO.become(PixelFormat) +def Init(flags): + if sys.platform == 'darwin': + from AppKit import NSApplication + NSApplication.sharedApplication() + return _Init(flags) -Init = external('SDL_Init', [Uint32], rffi.INT) +_Init = external('SDL_Init', [Uint32], rffi.INT) Quit = external('SDL_Quit', [], lltype.Void) SetVideoMode = external('SDL_SetVideoMode', [rffi.INT, rffi.INT, rffi.INT, Uint32], From karlb at codespeak.net Sat May 17 16:57:31 2008 From: karlb at codespeak.net (karlb at codespeak.net) Date: Sat, 17 May 2008 16:57:31 +0200 (CEST) Subject: [pypy-svn] r54841 - in pypy/dist/pypy/rlib/rsdl: . macosx-sdl-main Message-ID: <20080517145731.269912A017B@codespeak.net> Author: karlb Date: Sat May 17 16:57:27 2008 New Revision: 54841 Added: pypy/dist/pypy/rlib/rsdl/macosx-sdl-main/ pypy/dist/pypy/rlib/rsdl/macosx-sdl-main/SDLMain.h pypy/dist/pypy/rlib/rsdl/macosx-sdl-main/SDLMain.m Modified: pypy/dist/pypy/rlib/rsdl/RSDL.py Log: Added SDLMain.m/.h, which is required for SDL on MacOS X Modified: pypy/dist/pypy/rlib/rsdl/RSDL.py ============================================================================== --- pypy/dist/pypy/rlib/rsdl/RSDL.py (original) +++ pypy/dist/pypy/rlib/rsdl/RSDL.py Sat May 17 16:57:27 2008 @@ -8,7 +8,7 @@ includes = ['SDL.h'], include_dirs = ['/Library/Frameworks/SDL.framework/Versions/A/Headers'], link_extra = [ - '/Users/karl/ctypes-test/SDLMain.m', + 'macosx-sdl-main/SDLMain.m', '-I', '/Library/Frameworks/SDL.framework/Versions/A/Headers', ], frameworks = ['SDL', 'Cocoa'] Added: pypy/dist/pypy/rlib/rsdl/macosx-sdl-main/SDLMain.h ============================================================================== --- (empty file) +++ pypy/dist/pypy/rlib/rsdl/macosx-sdl-main/SDLMain.h Sat May 17 16:57:27 2008 @@ -0,0 +1,11 @@ +/* SDLMain.m - main entry point for our Cocoa-ized SDL app + Initial Version: Darrell Walisser + Non-NIB-Code & other changes: Max Horn + + Feel free to customize this file to suit your needs +*/ + +#import + + at interface SDLMain : NSObject + at end Added: pypy/dist/pypy/rlib/rsdl/macosx-sdl-main/SDLMain.m ============================================================================== --- (empty file) +++ pypy/dist/pypy/rlib/rsdl/macosx-sdl-main/SDLMain.m Sat May 17 16:57:27 2008 @@ -0,0 +1,384 @@ +/* SDLMain.m - main entry point for our Cocoa-ized SDL app + Initial Version: Darrell Walisser + Non-NIB-Code & other changes: Max Horn + + Feel free to customize this file to suit your needs +*/ + +#import "SDL.h" +#import "SDLMain.h" +#import /* for MAXPATHLEN */ +#import + +/* For some reaon, Apple removed setAppleMenu from the headers in 10.4, + but the method still is there and works. To avoid warnings, we declare + it ourselves here. */ + at interface NSApplication(SDL_Missing_Methods) +- (void)setAppleMenu:(NSMenu *)menu; + at end + +/* Use this flag to determine whether we use SDLMain.nib or not */ +#define SDL_USE_NIB_FILE 0 + +/* Use this flag to determine whether we use CPS (docking) or not */ +#define SDL_USE_CPS 1 +#ifdef SDL_USE_CPS +/* Portions of CPS.h */ +typedef struct CPSProcessSerNum +{ + UInt32 lo; + UInt32 hi; +} CPSProcessSerNum; + +extern OSErr CPSGetCurrentProcess( CPSProcessSerNum *psn); +extern OSErr CPSEnableForegroundOperation( CPSProcessSerNum *psn, UInt32 _arg2, UInt32 _arg3, UInt32 _arg4, UInt32 _arg5); +extern OSErr CPSSetFrontProcess( CPSProcessSerNum *psn); + +#endif /* SDL_USE_CPS */ + +static int gArgc; +static char **gArgv; +static BOOL gFinderLaunch; +static BOOL gCalledAppMainline = FALSE; + +static NSString *getApplicationName(void) +{ + NSDictionary *dict; + NSString *appName = 0; + + /* Determine the application name */ + dict = (NSDictionary *)CFBundleGetInfoDictionary(CFBundleGetMainBundle()); + if (dict) + appName = [dict objectForKey: @"CFBundleName"]; + + if (![appName length]) + appName = [[NSProcessInfo processInfo] processName]; + + return appName; +} + +#if SDL_USE_NIB_FILE +/* A helper category for NSString */ + at interface NSString (ReplaceSubString) +- (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString; + at end +#endif + + at interface SDLApplication : NSApplication + at end + + at implementation SDLApplication +/* Invoked from the Quit menu item */ +- (void)terminate:(id)sender +{ + /* Post a SDL_QUIT event */ + SDL_Event event; + event.type = SDL_QUIT; + SDL_PushEvent(&event); +} + at end + +/* The main class of the application, the application's delegate */ + at implementation SDLMain + +/* Set the working directory to the .app's parent directory */ +- (void) setupWorkingDirectory:(BOOL)shouldChdir +{ + if (shouldChdir) + { + char parentdir[MAXPATHLEN]; + CFURLRef url = CFBundleCopyBundleURL(CFBundleGetMainBundle()); + CFURLRef url2 = CFURLCreateCopyDeletingLastPathComponent(0, url); + if (CFURLGetFileSystemRepresentation(url2, true, (UInt8 *)parentdir, MAXPATHLEN)) { + assert ( chdir (parentdir) == 0 ); /* chdir to the binary app's parent */ + } + CFRelease(url); + CFRelease(url2); + } + +} + +#if SDL_USE_NIB_FILE + +/* Fix menu to contain the real app name instead of "SDL App" */ +- (void)fixMenu:(NSMenu *)aMenu withAppName:(NSString *)appName +{ + NSRange aRange; + NSEnumerator *enumerator; + NSMenuItem *menuItem; + + aRange = [[aMenu title] rangeOfString:@"SDL App"]; + if (aRange.length != 0) + [aMenu setTitle: [[aMenu title] stringByReplacingRange:aRange with:appName]]; + + enumerator = [[aMenu itemArray] objectEnumerator]; + while ((menuItem = [enumerator nextObject])) + { + aRange = [[menuItem title] rangeOfString:@"SDL App"]; + if (aRange.length != 0) + [menuItem setTitle: [[menuItem title] stringByReplacingRange:aRange with:appName]]; + if ([menuItem hasSubmenu]) + [self fixMenu:[menuItem submenu] withAppName:appName]; + } + [ aMenu sizeToFit ]; +} + +#else + +static void setApplicationMenu(void) +{ + /* warning: this code is very odd */ + NSMenu *appleMenu; + NSMenuItem *menuItem; + NSString *title; + NSString *appName; + + appName = getApplicationName(); + appleMenu = [[NSMenu alloc] initWithTitle:@""]; + + /* Add menu items */ + title = [@"About " stringByAppendingString:appName]; + [appleMenu addItemWithTitle:title action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""]; + + [appleMenu addItem:[NSMenuItem separatorItem]]; + + title = [@"Hide " stringByAppendingString:appName]; + [appleMenu addItemWithTitle:title action:@selector(hide:) keyEquivalent:@"h"]; + + menuItem = (NSMenuItem *)[appleMenu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"]; + [menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)]; + + [appleMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""]; + + [appleMenu addItem:[NSMenuItem separatorItem]]; + + title = [@"Quit " stringByAppendingString:appName]; + [appleMenu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"]; + + + /* Put menu into the menubar */ + menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""]; + [menuItem setSubmenu:appleMenu]; + [[NSApp mainMenu] addItem:menuItem]; + + /* Tell the application object that this is now the application menu */ + [NSApp setAppleMenu:appleMenu]; + + /* Finally give up our references to the objects */ + [appleMenu release]; + [menuItem release]; +} + +/* Create a window menu */ +static void setupWindowMenu(void) +{ + NSMenu *windowMenu; + NSMenuItem *windowMenuItem; + NSMenuItem *menuItem; + + windowMenu = [[NSMenu alloc] initWithTitle:@"Window"]; + + /* "Minimize" item */ + menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"]; + [windowMenu addItem:menuItem]; + [menuItem release]; + + /* Put menu into the menubar */ + windowMenuItem = [[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""]; + [windowMenuItem setSubmenu:windowMenu]; + [[NSApp mainMenu] addItem:windowMenuItem]; + + /* Tell the application object that this is now the window menu */ + [NSApp setWindowsMenu:windowMenu]; + + /* Finally give up our references to the objects */ + [windowMenu release]; + [windowMenuItem release]; +} + +/* Replacement for NSApplicationMain */ +static void CustomApplicationMain (int argc, char **argv) +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + SDLMain *sdlMain; + + /* Ensure the application object is initialised */ + [SDLApplication sharedApplication]; + +#ifdef SDL_USE_CPS + { + CPSProcessSerNum PSN; + /* Tell the dock about us */ + if (!CPSGetCurrentProcess(&PSN)) + if (!CPSEnableForegroundOperation(&PSN,0x03,0x3C,0x2C,0x1103)) + if (!CPSSetFrontProcess(&PSN)) + [SDLApplication sharedApplication]; + } +#endif /* SDL_USE_CPS */ + + /* Set up the menubar */ + [NSApp setMainMenu:[[NSMenu alloc] init]]; + setApplicationMenu(); + setupWindowMenu(); + + /* Create SDLMain and make it the app delegate */ + sdlMain = [[SDLMain alloc] init]; + [NSApp setDelegate:sdlMain]; + + /* Start the main event loop */ + [NSApp run]; + + [sdlMain release]; + [pool release]; +} + +#endif + + +/* + * Catch document open requests...this lets us notice files when the app + * was launched by double-clicking a document, or when a document was + * dragged/dropped on the app's icon. You need to have a + * CFBundleDocumentsType section in your Info.plist to get this message, + * apparently. + * + * Files are added to gArgv, so to the app, they'll look like command line + * arguments. Previously, apps launched from the finder had nothing but + * an argv[0]. + * + * This message may be received multiple times to open several docs on launch. + * + * This message is ignored once the app's mainline has been called. + */ +- (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename +{ + const char *temparg; + size_t arglen; + char *arg; + char **newargv; + + if (!gFinderLaunch) /* MacOS is passing command line args. */ + return FALSE; + + if (gCalledAppMainline) /* app has started, ignore this document. */ + return FALSE; + + temparg = [filename UTF8String]; + arglen = SDL_strlen(temparg) + 1; + arg = (char *) SDL_malloc(arglen); + if (arg == NULL) + return FALSE; + + newargv = (char **) realloc(gArgv, sizeof (char *) * (gArgc + 2)); + if (newargv == NULL) + { + SDL_free(arg); + return FALSE; + } + gArgv = newargv; + + SDL_strlcpy(arg, temparg, arglen); + gArgv[gArgc++] = arg; + gArgv[gArgc] = NULL; + return TRUE; +} + + +/* Called when the internal event loop has just started running */ +- (void) applicationDidFinishLaunching: (NSNotification *) note +{ + int status; + + /* Set the working directory to the .app's parent directory */ + [self setupWorkingDirectory:gFinderLaunch]; + +#if SDL_USE_NIB_FILE + /* Set the main menu to contain the real app name instead of "SDL App" */ + [self fixMenu:[NSApp mainMenu] withAppName:getApplicationName()]; +#endif + + /* Hand off to main application code */ + gCalledAppMainline = TRUE; + status = SDL_main (gArgc, gArgv); + + /* We're done, thank you for playing */ + exit(status); +} + at end + + + at implementation NSString (ReplaceSubString) + +- (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString +{ + unsigned int bufferSize; + unsigned int selfLen = [self length]; + unsigned int aStringLen = [aString length]; + unichar *buffer; + NSRange localRange; + NSString *result; + + bufferSize = selfLen + aStringLen - aRange.length; + buffer = NSAllocateMemoryPages(bufferSize*sizeof(unichar)); + + /* Get first part into buffer */ + localRange.location = 0; + localRange.length = aRange.location; + [self getCharacters:buffer range:localRange]; + + /* Get middle part into buffer */ + localRange.location = 0; + localRange.length = aStringLen; + [aString getCharacters:(buffer+aRange.location) range:localRange]; + + /* Get last part into buffer */ + localRange.location = aRange.location + aRange.length; + localRange.length = selfLen - localRange.location; + [self getCharacters:(buffer+aRange.location+aStringLen) range:localRange]; + + /* Build output string */ + result = [NSString stringWithCharacters:buffer length:bufferSize]; + + NSDeallocateMemoryPages(buffer, bufferSize); + + return result; +} + + at end + + + +#ifdef main +# undef main +#endif + + +/* Main entry point to executable - should *not* be SDL_main! */ +int main (int argc, char **argv) +{ + /* Copy the arguments into a global variable */ + /* This is passed if we are launched by double-clicking */ + if ( argc >= 2 && strncmp (argv[1], "-psn", 4) == 0 ) { + gArgv = (char **) SDL_malloc(sizeof (char *) * 2); + gArgv[0] = argv[0]; + gArgv[1] = NULL; + gArgc = 1; + gFinderLaunch = YES; + } else { + int i; + gArgc = argc; + gArgv = (char **) SDL_malloc(sizeof (char *) * (argc+1)); + for (i = 0; i <= argc; i++) + gArgv[i] = argv[i]; + gFinderLaunch = NO; + } + +#if SDL_USE_NIB_FILE + [SDLApplication poseAsClass:[NSApplication class]]; + NSApplicationMain (argc, argv); +#else + CustomApplicationMain (argc, argv); +#endif + return 0; +} + From fijal at codespeak.net Sat May 17 17:04:59 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 17 May 2008 17:04:59 +0200 (CEST) Subject: [pypy-svn] r54842 - in pypy/dist/pypy/lib: . app_test Message-ID: <20080517150459.CA766168567@codespeak.net> Author: fijal Date: Sat May 17 17:04:58 2008 New Revision: 54842 Added: pypy/dist/pypy/lib/app_test/test_datetime.py (contents, props changed) Modified: pypy/dist/pypy/lib/datetime.py Log: Make datetime.datetime print the same thing as under cpython Added: pypy/dist/pypy/lib/app_test/test_datetime.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/lib/app_test/test_datetime.py Sat May 17 17:04:58 2008 @@ -0,0 +1,7 @@ + +import datetime + +def test_repr(): + print datetime + expected = "datetime.datetime(1, 2, 3, 0, 0)" + assert repr(datetime.datetime(1,2,3)) == expected Modified: pypy/dist/pypy/lib/datetime.py ============================================================================== --- pypy/dist/pypy/lib/datetime.py (original) +++ pypy/dist/pypy/lib/datetime.py Sat May 17 17:04:58 2008 @@ -1561,8 +1561,10 @@ "Convert to formal string, for repr()." L = [self.__year, self.__month, self.__day, # These are never zero self.__hour, self.__minute, self.__second, self.__microsecond] - while L[-1] == 0: + if L[-1] == 0: del L[-1] + if L[-1] == 0: + del L[-1] s = ", ".join(map(str, L)) s = "%s(%s)" % ('datetime.' + self.__class__.__name__, s) if self._tzinfo is not None: From arigo at codespeak.net Sat May 17 17:12:23 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 17 May 2008 17:12:23 +0200 (CEST) Subject: [pypy-svn] r54843 - in pypy/dist/pypy/rlib/rsdl: . test Message-ID: <20080517151223.52403168567@codespeak.net> Author: arigo Date: Sat May 17 17:12:22 2008 New Revision: 54843 Modified: pypy/dist/pypy/rlib/rsdl/RSDL.py pypy/dist/pypy/rlib/rsdl/test/test_sdl_image.py Log: Some pixel manipulation routines, used to check that the loaded image is correct. Modified: pypy/dist/pypy/rlib/rsdl/RSDL.py ============================================================================== --- pypy/dist/pypy/rlib/rsdl/RSDL.py (original) +++ pypy/dist/pypy/rlib/rsdl/RSDL.py Sat May 17 17:12:22 2008 @@ -30,8 +30,11 @@ _compilation_info_ = eci Uint8 = platform.SimpleType('Uint8', rffi.INT) + Uint16 = platform.SimpleType('Uint16', rffi.INT) Uint32 = platform.SimpleType('Uint32', rffi.INT) + BYTEORDER = platform.ConstantInteger('SDL_BYTEORDER') + BIG_ENDIAN = platform.ConstantInteger('SDL_BIG_ENDIAN') INIT_VIDEO = platform.ConstantInteger('SDL_INIT_VIDEO') Rect = platform.Struct('SDL_Rect', [('x', rffi.INT), @@ -40,8 +43,11 @@ ('h', rffi.INT)]) Surface = platform.Struct('SDL_Surface', [('w', rffi.INT), ('h', rffi.INT), - ('format', PixelFormatPtr)]) - PixelFormat = platform.Struct('SDL_PixelFormat', []) + ('format', PixelFormatPtr), + ('pitch', rffi.INT), + ('pixels', rffi.UCHARP)]) + PixelFormat = platform.Struct('SDL_PixelFormat', + [('BytesPerPixel', rffi.INT)]) globals().update(platform.configure(CConfig)) @@ -49,6 +55,10 @@ SurfacePtr.TO.become(Surface) PixelFormatPtr.TO.become(PixelFormat) +Uint8P = lltype.Ptr(lltype.Array(Uint8, hints={'nolength': True})) +Uint16P = lltype.Ptr(lltype.Array(Uint16, hints={'nolength': True})) +Uint32P = lltype.Ptr(lltype.Array(Uint32, hints={'nolength': True})) + def Init(flags): if sys.platform == 'darwin': from AppKit import NSApplication @@ -66,7 +76,40 @@ Uint32, Uint32, Uint32, Uint32], SurfacePtr) +LockSurface = external('SDL_LockSurface', [SurfacePtr], rffi.INT) +UnlockSurface = external('SDL_UnlockSurface', [SurfacePtr], lltype.Void) FreeSurface = external('SDL_FreeSurface', [SurfacePtr], lltype.Void) MapRGB = external('SDL_MapRGB', [PixelFormatPtr, Uint8, Uint8, Uint8], Uint32) +GetRGB = external('SDL_GetRGB', [Uint32, PixelFormatPtr, + Uint8P, Uint8P, Uint8P], lltype.Void) FillRect = external('SDL_FillRect', [SurfacePtr, RectPtr, Uint32], rffi.INT) + + +def getpixel(image, x, y): + """Return the pixel value at (x, y) + NOTE: The surface must be locked before calling this! + """ + bpp = rffi.getintfield(image.c_format, 'c_BytesPerPixel') + pitch = rffi.getintfield(image, 'c_pitch') + # Here p is the address to the pixel we want to retrieve + p = rffi.ptradd(image.c_pixels, y * pitch + x * bpp) + if bpp == 1: + return rffi.cast(Uint32, p[0]) + elif bpp == 2: + p = rffi.cast(Uint16P, p) + return rffi.cast(Uint32, p[0]) + elif bpp == 3: + p0 = rffi.cast(lltype.Signed, p[0]) + p1 = rffi.cast(lltype.Signed, p[1]) + p2 = rffi.cast(lltype.Signed, p[2]) + if BYTEORDER == BIG_ENDIAN: + result = p0 << 16 | p1 << 8 | p2 + else: + result = p0 | p1 << 8 | p2 << 16 + return rffi.cast(Uint32, result) + elif bpp == 4: + p = rffi.cast(Uint32P, p) + return p[0] + else: + raise ValueError("bad BytesPerPixel") Modified: pypy/dist/pypy/rlib/rsdl/test/test_sdl_image.py ============================================================================== --- pypy/dist/pypy/rlib/rsdl/test/test_sdl_image.py (original) +++ pypy/dist/pypy/rlib/rsdl/test/test_sdl_image.py Sat May 17 17:12:22 2008 @@ -1,7 +1,7 @@ import py, os import autopath from pypy.rlib.rsdl import RSDL, RIMG -from pypy.rpython.lltypesystem import rffi +from pypy.rpython.lltypesystem import lltype, rffi def test_load_image(): @@ -11,3 +11,41 @@ assert rffi.getintfield(image, 'c_w') == 17 assert rffi.getintfield(image, 'c_h') == 23 RSDL.FreeSurface(image) + +def test_image_pixels(): + for filename in ["demo.jpg", "demo.png"]: + image = RIMG.Load(os.path.join(autopath.this_dir, filename)) + assert image + assert rffi.getintfield(image.c_format, 'c_BytesPerPixel') in (3, 4) + RSDL.LockSurface(image) + result = {} + try: + rgb = lltype.malloc(rffi.CArray(RSDL.Uint8), 3, flavor='raw') + try: + for y in range(23): + for x in range(17): + color = RSDL.getpixel(image, x, y) + RSDL.GetRGB(color, + image.c_format, + rffi.ptradd(rgb, 0), + rffi.ptradd(rgb, 1), + rffi.ptradd(rgb, 2)) + r = rffi.cast(lltype.Signed, rgb[0]) + g = rffi.cast(lltype.Signed, rgb[1]) + b = rffi.cast(lltype.Signed, rgb[2]) + result[x, y] = r, g, b + finally: + lltype.free(rgb, flavor='raw') + finally: + RSDL.UnlockSurface(image) + RSDL.FreeSurface(image) + for y in range(23): + for x in range(17): + f = (x*17 + y*23) / float(17*17+23*23) + expected_r = int(255.0 * (1.0-f)) + expected_g = 0 + expected_b = int(255.0 * f) + r, g, b = result[x, y] + assert abs(r-expected_r) < 10 + assert abs(g-expected_g) < 10 + assert abs(b-expected_b) < 10 From arigo at codespeak.net Sat May 17 17:39:09 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 17 May 2008 17:39:09 +0200 (CEST) Subject: [pypy-svn] r54847 - pypy/dist/pypy/rlib/rsdl/test Message-ID: <20080517153909.CED66168563@codespeak.net> Author: arigo Date: Sat May 17 17:39:08 2008 New Revision: 54847 Modified: pypy/dist/pypy/rlib/rsdl/test/test_sdl_image.py Log: Speed up test_image_pixels(). Modified: pypy/dist/pypy/rlib/rsdl/test/test_sdl_image.py ============================================================================== --- pypy/dist/pypy/rlib/rsdl/test/test_sdl_image.py (original) +++ pypy/dist/pypy/rlib/rsdl/test/test_sdl_image.py Sat May 17 17:39:08 2008 @@ -23,7 +23,7 @@ rgb = lltype.malloc(rffi.CArray(RSDL.Uint8), 3, flavor='raw') try: for y in range(23): - for x in range(17): + for x in range(y % 13, 17, 13): color = RSDL.getpixel(image, x, y) RSDL.GetRGB(color, image.c_format, @@ -39,13 +39,12 @@ finally: RSDL.UnlockSurface(image) RSDL.FreeSurface(image) - for y in range(23): - for x in range(17): - f = (x*17 + y*23) / float(17*17+23*23) - expected_r = int(255.0 * (1.0-f)) - expected_g = 0 - expected_b = int(255.0 * f) - r, g, b = result[x, y] - assert abs(r-expected_r) < 10 - assert abs(g-expected_g) < 10 - assert abs(b-expected_b) < 10 + for x, y in result: + f = (x*17 + y*23) / float(17*17+23*23) + expected_r = int(255.0 * (1.0-f)) + expected_g = 0 + expected_b = int(255.0 * f) + r, g, b = result[x, y] + assert abs(r-expected_r) < 10 + assert abs(g-expected_g) < 10 + assert abs(b-expected_b) < 10 From karlb at codespeak.net Sat May 17 17:40:55 2008 From: karlb at codespeak.net (karlb at codespeak.net) Date: Sat, 17 May 2008 17:40:55 +0200 (CEST) Subject: [pypy-svn] r54848 - in pypy/dist/pypy/rlib/rsdl: . test Message-ID: <20080517154055.31D5A168563@codespeak.net> Author: karlb Date: Sat May 17 17:40:54 2008 New Revision: 54848 Modified: pypy/dist/pypy/rlib/rsdl/RSDL.py pypy/dist/pypy/rlib/rsdl/test/test_video.py Log: Added support for RSDL.BlitRect Modified: pypy/dist/pypy/rlib/rsdl/RSDL.py ============================================================================== --- pypy/dist/pypy/rlib/rsdl/RSDL.py (original) +++ pypy/dist/pypy/rlib/rsdl/RSDL.py Sat May 17 17:40:54 2008 @@ -84,7 +84,7 @@ GetRGB = external('SDL_GetRGB', [Uint32, PixelFormatPtr, Uint8P, Uint8P, Uint8P], lltype.Void) FillRect = external('SDL_FillRect', [SurfacePtr, RectPtr, Uint32], rffi.INT) - +BlitSurface = external('SDL_UpperBlit', [SurfacePtr, RectPtr, SurfacePtr, RectPtr], rffi.INT) def getpixel(image, x, y): """Return the pixel value at (x, y) Modified: pypy/dist/pypy/rlib/rsdl/test/test_video.py ============================================================================== --- pypy/dist/pypy/rlib/rsdl/test/test_video.py (original) +++ pypy/dist/pypy/rlib/rsdl/test/test_video.py Sat May 17 17:40:54 2008 @@ -18,8 +18,8 @@ py.test.skip("'--view' not specified, " "skipping tests that open a window") assert RSDL.Init(RSDL.INIT_VIDEO) >= 0 - self.surface = RSDL.SetVideoMode(640, 480, 32, 0) - assert self.surface + self.screen = RSDL.SetVideoMode(640, 480, 32, 0) + assert self.screen def check(self, msg): if sys.stdout.isatty(): @@ -34,14 +34,37 @@ pass # only checks that opening and closing the window works def test_fillrect_full(self): - fmt = self.surface.c_format + fmt = self.screen.c_format for colorname, r, g, b in [('dark red', 128, 0, 0), ('yellow', 255, 255, 0), ('blue', 0, 0, 255)]: color = RSDL.MapRGB(fmt, r, g, b) - RSDL.FillRect(self.surface, lltype.nullptr(RSDL.Rect), color) - RSDL.Flip(self.surface) + RSDL.FillRect(self.screen, lltype.nullptr(RSDL.Rect), color) + RSDL.Flip(self.screen) self.check("Screen filled with %s" % colorname) + def test_blit_rect(self): + surface = RSDL.CreateRGBSurface(0, 150, 50, 32, + r_uint(0x000000FF), + r_uint(0x0000FF00), + r_uint(0x00FF0000), + r_uint(0xFF000000)) + fmt = surface.c_format + color = RSDL.MapRGB(fmt, 255, 0, 0) + RSDL.FillRect(surface, lltype.nullptr(RSDL.Rect), color) + dstrect = lltype.malloc(RSDL.Rect, flavor='raw') + try: + rffi.setintfield(dstrect, 'c_x', 10) + rffi.setintfield(dstrect, 'c_y', 10) + rffi.setintfield(dstrect, 'c_w', 150) + rffi.setintfield(dstrect, 'c_h', 50) + RSDL.BlitSurface(surface, lltype.nullptr(RSDL.Rect), self.screen, dstrect) + RSDL.Flip(self.screen) + finally: + lltype.free(dstrect, flavor='raw') + RSDL.FreeSurface(surface) + self.check("Red rectangle(150px * 50px) at the top left, 10 pixels from the border") + def teardown_method(self, meth): RSDL.Quit() + From afa at codespeak.net Sat May 17 17:41:31 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Sat, 17 May 2008 17:41:31 +0200 (CEST) Subject: [pypy-svn] r54849 - pypy/branch/win32port Message-ID: <20080517154131.DEC2F16856D@codespeak.net> Author: afa Date: Sat May 17 17:41:30 2008 New Revision: 54849 Removed: pypy/branch/win32port/ Log: remove wrongly created branch From afa at codespeak.net Sat May 17 17:42:13 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Sat, 17 May 2008 17:42:13 +0200 (CEST) Subject: [pypy-svn] r54850 - pypy/branch/win32port Message-ID: <20080517154213.3F05E168571@codespeak.net> Author: afa Date: Sat May 17 17:42:12 2008 New Revision: 54850 Added: pypy/branch/win32port/ - copied from r54849, pypy/dist/ Log: recreate branch for win32-related work From fijal at codespeak.net Sat May 17 17:43:30 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 17 May 2008 17:43:30 +0200 (CEST) Subject: [pypy-svn] r54851 - pypy/django/django/dispatch Message-ID: <20080517154330.BA5EE16857D@codespeak.net> Author: fijal Date: Sat May 17 17:43:29 2008 New Revision: 54851 Added: pypy/django/django/dispatch/test_robustapply.py (contents, props changed) Log: (pedronis, fijal) write a decent test suite for robust apply Added: pypy/django/django/dispatch/test_robustapply.py ============================================================================== --- (empty file) +++ pypy/django/django/dispatch/test_robustapply.py Sat May 17 17:43:29 2008 @@ -0,0 +1,78 @@ + +import py +from robustapply import function + +def test_function(): + def f(): + pass + assert function(f) == (f, f.func_code, 0) + +def test_method(): + class A: + def m(self, stuff): + pass + + obj = A() + assert function(obj.m) == (obj.m, A.m.im_func.func_code, 1) + +def test_method_unbound(): + class A: + def m(self, stuff): + pass + assert function(A.m) == (A.m, A.m.im_func.func_code, 1) + +def test_method_newstyle(): + class A(object): + def m(self, stuff): + pass + + obj = A() + assert function(obj.m) == (obj.m, A.m.im_func.func_code, 1) + +def test_method_unbound_newstyle(): + class A(object): + def m(self, stuff): + pass + assert function(A.m) == (A.m, A.m.im_func.func_code, 1) + +def test_class(): + class A: + def __init__(self): + pass + py.test.raises(ValueError, function, A) + +def test_newstyle_class(): + class A(object): + def __init__(self): + pass + py.test.raises(ValueError, function, A) + +def test_class_instance(): + class A: + def __call__(self): + pass + + obj = A() + assert function(obj) == (obj.__call__, obj.__call__.im_func.func_code, 1) + +def test_newclass_instance(): + class A(object): + def __call__(self): + pass + + obj = A() + assert function(obj) == (obj.__call__, obj.__call__.im_func.func_code, 1) + +def test_static_class_methods(): + class A(object): + @staticmethod + def a(): + pass + + @classmethod + def b(cls): + pass + + obj = A() + assert function(obj.a) == (obj.a, obj.a.func_code, 0) + assert function(obj.b) == (obj.b, obj.b.im_func.func_code, 1) From fijal at codespeak.net Sat May 17 17:49:27 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 17 May 2008 17:49:27 +0200 (CEST) Subject: [pypy-svn] r54852 - pypy/django/django/dispatch Message-ID: <20080517154927.CDBC8168536@codespeak.net> Author: fijal Date: Sat May 17 17:49:26 2008 New Revision: 54852 Modified: pypy/django/django/dispatch/robustapply.py pypy/django/django/dispatch/test_robustapply.py Log: Make pypy run robustapply Modified: pypy/django/django/dispatch/robustapply.py ============================================================================== --- pypy/django/django/dispatch/robustapply.py (original) +++ pypy/django/django/dispatch/robustapply.py Sat May 17 17:49:26 2008 @@ -14,17 +14,26 @@ If fromMethod is true, then the callable already has its first argument bound """ - if hasattr(receiver, '__call__'): - # receiver is a class instance; assume it is callable. - # Reassign receiver to the actual method that will be called. - if hasattr( receiver.__call__, 'im_func') or hasattr( receiver.__call__, 'im_code'): - receiver = receiver.__call__ - if hasattr( receiver, 'im_func' ): - # an instance-method... + if hasattr(receiver, 'im_func'): return receiver, receiver.im_func.func_code, 1 - elif not hasattr( receiver, 'func_code'): + elif hasattr(receiver, 'func_code'): + return receiver, receiver.func_code, 0 + elif hasattr(receiver, '__call__'): + return function(receiver.__call__) + else: raise ValueError('unknown reciever type %s %s'%(receiver, type(receiver))) - return receiver, receiver.func_code, 0 + +# if hasattr(receiver, '__call__'): +# # receiver is a class instance; assume it is callable. +# # Reassign receiver to the actual method that will be called. +# if hasattr( receiver.__call__, 'im_func') or hasattr( receiver.__call__, 'im_code'): +# receiver = receiver.__call__ +# if hasattr( receiver, 'im_func' ): +# # an instance-method... +# return receiver, receiver.im_func.func_code, 1 +# elif not hasattr( receiver, 'func_code'): +# raise ValueError('unknown reciever type %s %s'%(receiver, type(receiver))) +# return receiver, receiver.func_code, 0 def robustApply(receiver, *arguments, **named): """Call receiver with arguments and an appropriate subset of named Modified: pypy/django/django/dispatch/test_robustapply.py ============================================================================== --- pypy/django/django/dispatch/test_robustapply.py (original) +++ pypy/django/django/dispatch/test_robustapply.py Sat May 17 17:49:26 2008 @@ -36,12 +36,14 @@ assert function(A.m) == (A.m, A.m.im_func.func_code, 1) def test_class(): + py.test.skip("Explodes on top of pypy-c") class A: def __init__(self): pass py.test.raises(ValueError, function, A) def test_newstyle_class(): + py.test.skip("Explode on top of pypy-c") class A(object): def __init__(self): pass From fijal at codespeak.net Sat May 17 17:50:56 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 17 May 2008 17:50:56 +0200 (CEST) Subject: [pypy-svn] r54853 - pypy/django/tests Message-ID: <20080517155056.2D371168572@codespeak.net> Author: fijal Date: Sat May 17 17:50:55 2008 New Revision: 54853 Added: pypy/django/tests/settings.py (contents, props changed) Log: settings.py necessary for test running Added: pypy/django/tests/settings.py ============================================================================== --- (empty file) +++ pypy/django/tests/settings.py Sat May 17 17:50:55 2008 @@ -0,0 +1,2 @@ +ROOT_URLCONF="" +DATABASE_ENGINE="sqlite3" From arigo at codespeak.net Sat May 17 17:54:35 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 17 May 2008 17:54:35 +0200 (CEST) Subject: [pypy-svn] r54854 - in pypy/dist/pypy/rlib/rsdl: . test Message-ID: <20080517155435.5644716857B@codespeak.net> Author: arigo Date: Sat May 17 17:54:33 2008 New Revision: 54854 Modified: pypy/dist/pypy/rlib/rsdl/RSDL.py pypy/dist/pypy/rlib/rsdl/test/test_video.py Log: SDL_WM_SetCaption. Modified: pypy/dist/pypy/rlib/rsdl/RSDL.py ============================================================================== --- pypy/dist/pypy/rlib/rsdl/RSDL.py (original) +++ pypy/dist/pypy/rlib/rsdl/RSDL.py Sat May 17 17:54:33 2008 @@ -70,6 +70,8 @@ SetVideoMode = external('SDL_SetVideoMode', [rffi.INT, rffi.INT, rffi.INT, Uint32], SurfacePtr) +WM_SetCaption = external('SDL_WM_SetCaption', [rffi.CCHARP, rffi.CCHARP], + lltype.Void) Flip = external('SDL_Flip', [SurfacePtr], rffi.INT) CreateRGBSurface = external('SDL_CreateRGBSurface', [Uint32, rffi.INT, rffi.INT, rffi.INT, Modified: pypy/dist/pypy/rlib/rsdl/test/test_video.py ============================================================================== --- pypy/dist/pypy/rlib/rsdl/test/test_video.py (original) +++ pypy/dist/pypy/rlib/rsdl/test/test_video.py Sat May 17 17:54:33 2008 @@ -43,6 +43,10 @@ RSDL.Flip(self.screen) self.check("Screen filled with %s" % colorname) + def test_caption(self): + RSDL.WM_SetCaption("Hello World!", "Hello World!") + self.check('The window caption is "Hello World!"') + def test_blit_rect(self): surface = RSDL.CreateRGBSurface(0, 150, 50, 32, r_uint(0x000000FF), From afa at codespeak.net Sat May 17 18:03:48 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Sat, 17 May 2008 18:03:48 +0200 (CEST) Subject: [pypy-svn] r54855 - in pypy/branch/win32port/pypy: config rlib Message-ID: <20080517160348.9600216857D@codespeak.net> Author: afa Date: Sat May 17 18:03:42 2008 New Revision: 54855 Modified: pypy/branch/win32port/pypy/config/pypyoption.py pypy/branch/win32port/pypy/rlib/getnameinfo.py Log: Attempt to translate the _socket module on win32 Modified: pypy/branch/win32port/pypy/config/pypyoption.py ============================================================================== --- pypy/branch/win32port/pypy/config/pypyoption.py (original) +++ pypy/branch/win32port/pypy/config/pypyoption.py Sat May 17 18:03:42 2008 @@ -40,7 +40,7 @@ del working_modules["_rawffi"] # modules with broken windows support del working_modules["mmap"] # MLS - Added 5/11/08 - broken - del working_modules["_socket"] # MLS - Added 5/11/08 - broken + #del working_modules["_socket"] # MLS - Added 5/11/08 - broken del working_modules["select"] # MLS - Added 5/11/08 - broken Modified: pypy/branch/win32port/pypy/rlib/getnameinfo.py ============================================================================== --- pypy/branch/win32port/pypy/rlib/getnameinfo.py (original) +++ pypy/branch/win32port/pypy/rlib/getnameinfo.py Sat May 17 18:03:42 2008 @@ -4,7 +4,7 @@ """ from pypy.rlib import _rsocket_rffi as _c from pypy.rlib.rsocket import RSocketError, GAIError -from pypy.rpython.lltypesystem import lltype, rffi +from pypy.rpython.lltypesystem import lltype, rffi, ll_str from pypy.rlib.rarithmetic import r_uint NI_NOFQDN = 0x00000001 @@ -24,7 +24,7 @@ if sp: serv = rffi.charp2str(sp.c_s_name) else: - serv = "%d" % _c.ntohs(sin_port) + serv = ll_str.ll_int2dec(r_uint(_c.ntohs(sin_port))) return serv From fijal at codespeak.net Sat May 17 18:06:04 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 17 May 2008 18:06:04 +0200 (CEST) Subject: [pypy-svn] r54856 - in pypy/django/django: core/management/commands db/backends/sqlite3 db/models Message-ID: <20080517160604.4B238168549@codespeak.net> Author: fijal Date: Sat May 17 18:06:02 2008 New Revision: 54856 Modified: pypy/django/django/core/management/commands/syncdb.py pypy/django/django/db/backends/sqlite3/base.py pypy/django/django/db/models/base.py pypy/django/django/db/models/options.py Log: (pedronis, fijal) * Fix places where djange used details of oldstyle classes * Import pysqlite2 by default Modified: pypy/django/django/core/management/commands/syncdb.py ============================================================================== --- pypy/django/django/core/management/commands/syncdb.py (original) +++ pypy/django/django/core/management/commands/syncdb.py Sat May 17 18:06:02 2008 @@ -34,7 +34,8 @@ try: __import__(app_name + '.management', {}, {}, ['']) except ImportError, exc: - if not exc.args[0].startswith('No module named management'): + if 'management' not in exc.args[0]: + #if not exc.args[0].startswith('No module named management'): raise cursor = connection.cursor() Modified: pypy/django/django/db/backends/sqlite3/base.py ============================================================================== --- pypy/django/django/db/backends/sqlite3/base.py (original) +++ pypy/django/django/db/backends/sqlite3/base.py Sat May 17 18:06:02 2008 @@ -8,10 +8,10 @@ from django.db.backends import BaseDatabaseWrapper, BaseDatabaseFeatures, BaseDatabaseOperations, util try: - try: - from sqlite3 import dbapi2 as Database - except ImportError: - from pysqlite2 import dbapi2 as Database + #try: + # from sqlite3 import dbapi2 as Database + #except ImportError: + from pysqlite2 import dbapi2 as Database except ImportError, e: import sys from django.core.exceptions import ImproperlyConfigured Modified: pypy/django/django/db/models/base.py ============================================================================== --- pypy/django/django/db/models/base.py (original) +++ pypy/django/django/db/models/base.py Sat May 17 18:06:02 2008 @@ -135,7 +135,7 @@ def add_to_class(cls, name, value): if name == 'Admin': - assert type(value) == types.ClassType, "%r attribute of %s model must be a class, not a %s object" % (name, cls.__name__, type(value)) + assert type(value) in (types.ClassType, type), "%r attribute of %s model must be a class, not a %s object" % (name, cls.__name__, type(value)) value = AdminOptions(**dict([(k, v) for k, v in value.__dict__.items() if not k.startswith('_')])) if hasattr(value, 'contribute_to_class'): value.contribute_to_class(cls, name) Modified: pypy/django/django/db/models/options.py ============================================================================== --- pypy/django/django/db/models/options.py (original) +++ pypy/django/django/db/models/options.py Sat May 17 18:06:02 2008 @@ -58,6 +58,9 @@ meta_attrs = self.meta.__dict__.copy() del meta_attrs['__module__'] del meta_attrs['__doc__'] + for name in ['__dict__', '__weakref__']: + if name in meta_attrs: + del meta_attrs[name] for attr_name in DEFAULT_NAMES: if attr_name in meta_attrs: setattr(self, attr_name, meta_attrs.pop(attr_name)) From fijal at codespeak.net Sat May 17 18:07:54 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 17 May 2008 18:07:54 +0200 (CEST) Subject: [pypy-svn] r54857 - in pypy/django: . django django/bin django/bin/profiling django/conf django/conf/app_template django/conf/project_template django/conf/urls django/contrib django/contrib/admin django/contrib/admin/templatetags django/contrib/admin/views django/contrib/auth django/contrib/auth/handlers django/contrib/comments django/contrib/comments/templatetags django/contrib/comments/urls django/contrib/comments/views django/contrib/contenttypes django/contrib/csrf django/contrib/databrowse django/contrib/databrowse/plugins django/contrib/flatpages django/contrib/formtools django/contrib/humanize django/contrib/humanize/templatetags django/contrib/localflavor django/contrib/localflavor/ar django/contrib/localflavor/au django/contrib/localflavor/br django/contrib/localflavor/ca django/contrib/localflavor/ch django/contrib/localflavor/cl django/contrib/localflavor/de django/contrib/localflavor/es django/contrib/localflavor/fi django/contrib/localflavor/fr django/contrib/localflavor/generic django/contrib/localflavor/in_ django/contrib/localflavor/is_ django/contrib/localflavor/it django/contrib/localflavor/jp django/contrib/localflavor/mx django/contrib/localflavor/nl django/contrib/localflavor/no django/contrib/localflavor/pe django/contrib/localflavor/pl django/contrib/localflavor/sk django/contrib/localflavor/uk django/contrib/localflavor/us django/contrib/localflavor/za django/contrib/markup django/contrib/markup/templatetags django/contrib/redirects django/contrib/sessions django/contrib/sessions/backends django/contrib/sitemaps django/contrib/sites django/contrib/syndication django/contrib/webdesign django/contrib/webdesign/templatetags django/core django/core/cache django/core/cache/backends django/core/handlers django/core/management django/core/management/commands django/core/serializers django/core/servers django/db django/db/backends django/db/backends/dummy django/db/backends/mysql django/db/backends/mysql_old django/db/backends/oracle django/db/backends/postgresql django/db/backends/postgresql_psycopg2 django/db/backends/sqlite3 django/db/models django/db/models/fields django/db/models/sql django/dispatch django/forms django/http django/middleware django/newforms django/newforms/extras django/oldforms django/shortcuts django/template django/template/loaders django/templatetags django/test django/utils django/utils/simplejson django/utils/translation django/views django/views/decorators django/views/generic docs examples examples/hello tests tests/modeltests tests/modeltests/basic tests/modeltests/choices tests/modeltests/custom_columns tests/modeltests/custom_managers tests/modeltests/custom_methods tests/modeltests/custom_pk tests/modeltests/empty tests/modeltests/field_defaults tests/modeltests/field_subclassing tests/modeltests/fixtures tests/modeltests/generic_relations tests/modeltests/get_latest tests/modeltests/get_object_or_404 tests/modeltests/get_or_create tests/modeltests/invalid_models tests/modeltests/lookup tests/modeltests/m2m_and_m2o tests/modeltests/m2m_intermediary tests/modeltests/m2m_multiple tests/modeltests/m2m_recursive tests/modeltests/m2o_recursive tests/modeltests/m2o_recursive2 tests/modeltests/manipulators tests/modeltests/many_to_many tests/modeltests/many_to_one tests/modeltests/many_to_one_null tests/modeltests/model_forms tests/modeltests/model_inheritance tests/modeltests/mutually_referential tests/modeltests/one_to_one tests/modeltests/or_lookups tests/modeltests/order_with_respect_to tests/modeltests/ordering tests/modeltests/pagination tests/modeltests/properties tests/modeltests/reserved_names tests/modeltests/reverse_lookup tests/modeltests/save_delete_hooks tests/modeltests/select_related tests/modeltests/serializers tests/modeltests/signals tests/modeltests/str tests/modeltests/test_client tests/modeltests/transactions tests/modeltests/update tests/modeltests/user_commands tests/modeltests/user_commands/management tests/modeltests/user_commands/management/commands tests/modeltests/validation tests/regressiontests tests/regressiontests/auth_backends tests/regressiontests/backends tests/regressiontests/bug639 tests/regressiontests/cache tests/regressiontests/datastructures tests/regressiontests/datatypes tests/regressiontests/dateformat tests/regressiontests/db_typecasts tests/regressiontests/decorators tests/regressiontests/defaultfilters tests/regressiontests/dispatch tests/regressiontests/dispatch/tests tests/regressiontests/fixtures_regress tests/regressiontests/forms tests/regressiontests/forms/localflavor tests/regressiontests/httpwrappers tests/regressiontests/humanize tests/regressiontests/i18n tests/regressiontests/initial_sql_regress tests/regressiontests/invalid_admin_options tests/regressiontests/many_to_one_regress tests/regressiontests/max_lengths tests/regressiontests/maxlength tests/regressiontests/middleware tests/regressiontests/model_fields tests/regressiontests/model_regress tests/regressiontests/null_queries tests/regressiontests/one_to_one_regress tests/regressiontests/queries tests/regressiontests/requests tests/regressiontests/serializers_regress tests/regressiontests/string_lookup tests/regressiontests/syndication tests/regressiontests/templates tests/regressiontests/test_client_regress tests/regressiontests/text tests/regressiontests/urlpatterns_reverse tests/regressiontests/utils tests/regressiontests/views tests/regressiontests/views/media tests/regressiontests/views/tests tests/regressiontests/views/tests/generic Message-ID: <20080517160754.D4BF616857C@codespeak.net> Author: fijal Date: Sat May 17 18:07:51 2008 New Revision: 54857 Modified: pypy/django/ (props changed) pypy/django/django/ (props changed) pypy/django/django/bin/ (props changed) pypy/django/django/bin/profiling/ (props changed) pypy/django/django/conf/ (props changed) pypy/django/django/conf/app_template/ (props changed) pypy/django/django/conf/project_template/ (props changed) pypy/django/django/conf/urls/ (props changed) pypy/django/django/contrib/ (props changed) pypy/django/django/contrib/admin/ (props changed) pypy/django/django/contrib/admin/templatetags/ (props changed) pypy/django/django/contrib/admin/views/ (props changed) pypy/django/django/contrib/auth/ (props changed) pypy/django/django/contrib/auth/handlers/ (props changed) pypy/django/django/contrib/comments/ (props changed) pypy/django/django/contrib/comments/templatetags/ (props changed) pypy/django/django/contrib/comments/urls/ (props changed) pypy/django/django/contrib/comments/views/ (props changed) pypy/django/django/contrib/contenttypes/ (props changed) pypy/django/django/contrib/csrf/ (props changed) pypy/django/django/contrib/databrowse/ (props changed) pypy/django/django/contrib/databrowse/plugins/ (props changed) pypy/django/django/contrib/flatpages/ (props changed) pypy/django/django/contrib/formtools/ (props changed) pypy/django/django/contrib/humanize/ (props changed) pypy/django/django/contrib/humanize/templatetags/ (props changed) pypy/django/django/contrib/localflavor/ (props changed) pypy/django/django/contrib/localflavor/ar/ (props changed) pypy/django/django/contrib/localflavor/au/ (props changed) pypy/django/django/contrib/localflavor/br/ (props changed) pypy/django/django/contrib/localflavor/ca/ (props changed) pypy/django/django/contrib/localflavor/ch/ (props changed) pypy/django/django/contrib/localflavor/cl/ (props changed) pypy/django/django/contrib/localflavor/de/ (props changed) pypy/django/django/contrib/localflavor/es/ (props changed) pypy/django/django/contrib/localflavor/fi/ (props changed) pypy/django/django/contrib/localflavor/fr/ (props changed) pypy/django/django/contrib/localflavor/generic/ (props changed) pypy/django/django/contrib/localflavor/in_/ (props changed) pypy/django/django/contrib/localflavor/is_/ (props changed) pypy/django/django/contrib/localflavor/it/ (props changed) pypy/django/django/contrib/localflavor/jp/ (props changed) pypy/django/django/contrib/localflavor/mx/ (props changed) pypy/django/django/contrib/localflavor/nl/ (props changed) pypy/django/django/contrib/localflavor/no/ (props changed) pypy/django/django/contrib/localflavor/pe/ (props changed) pypy/django/django/contrib/localflavor/pl/ (props changed) pypy/django/django/contrib/localflavor/sk/ (props changed) pypy/django/django/contrib/localflavor/uk/ (props changed) pypy/django/django/contrib/localflavor/us/ (props changed) pypy/django/django/contrib/localflavor/za/ (props changed) pypy/django/django/contrib/markup/ (props changed) pypy/django/django/contrib/markup/templatetags/ (props changed) pypy/django/django/contrib/redirects/ (props changed) pypy/django/django/contrib/sessions/ (props changed) pypy/django/django/contrib/sessions/backends/ (props changed) pypy/django/django/contrib/sitemaps/ (props changed) pypy/django/django/contrib/sites/ (props changed) pypy/django/django/contrib/syndication/ (props changed) pypy/django/django/contrib/webdesign/ (props changed) pypy/django/django/contrib/webdesign/templatetags/ (props changed) pypy/django/django/core/ (props changed) pypy/django/django/core/cache/ (props changed) pypy/django/django/core/cache/backends/ (props changed) pypy/django/django/core/handlers/ (props changed) pypy/django/django/core/management/ (props changed) pypy/django/django/core/management/commands/ (props changed) pypy/django/django/core/serializers/ (props changed) pypy/django/django/core/servers/ (props changed) pypy/django/django/db/ (props changed) pypy/django/django/db/backends/ (props changed) pypy/django/django/db/backends/dummy/ (props changed) pypy/django/django/db/backends/mysql/ (props changed) pypy/django/django/db/backends/mysql_old/ (props changed) pypy/django/django/db/backends/oracle/ (props changed) pypy/django/django/db/backends/postgresql/ (props changed) pypy/django/django/db/backends/postgresql_psycopg2/ (props changed) pypy/django/django/db/backends/sqlite3/ (props changed) pypy/django/django/db/models/ (props changed) pypy/django/django/db/models/fields/ (props changed) pypy/django/django/db/models/sql/ (props changed) pypy/django/django/dispatch/ (props changed) pypy/django/django/forms/ (props changed) pypy/django/django/http/ (props changed) pypy/django/django/middleware/ (props changed) pypy/django/django/newforms/ (props changed) pypy/django/django/newforms/extras/ (props changed) pypy/django/django/oldforms/ (props changed) pypy/django/django/shortcuts/ (props changed) pypy/django/django/template/ (props changed) pypy/django/django/template/loaders/ (props changed) pypy/django/django/templatetags/ (props changed) pypy/django/django/test/ (props changed) pypy/django/django/utils/ (props changed) pypy/django/django/utils/simplejson/ (props changed) pypy/django/django/utils/translation/ (props changed) pypy/django/django/views/ (props changed) pypy/django/django/views/decorators/ (props changed) pypy/django/django/views/generic/ (props changed) pypy/django/docs/ (props changed) pypy/django/examples/ (props changed) pypy/django/examples/hello/ (props changed) pypy/django/tests/ (props changed) pypy/django/tests/modeltests/ (props changed) pypy/django/tests/modeltests/basic/ (props changed) pypy/django/tests/modeltests/choices/ (props changed) pypy/django/tests/modeltests/custom_columns/ (props changed) pypy/django/tests/modeltests/custom_managers/ (props changed) pypy/django/tests/modeltests/custom_methods/ (props changed) pypy/django/tests/modeltests/custom_pk/ (props changed) pypy/django/tests/modeltests/empty/ (props changed) pypy/django/tests/modeltests/field_defaults/ (props changed) pypy/django/tests/modeltests/field_subclassing/ (props changed) pypy/django/tests/modeltests/fixtures/ (props changed) pypy/django/tests/modeltests/generic_relations/ (props changed) pypy/django/tests/modeltests/get_latest/ (props changed) pypy/django/tests/modeltests/get_object_or_404/ (props changed) pypy/django/tests/modeltests/get_or_create/ (props changed) pypy/django/tests/modeltests/invalid_models/ (props changed) pypy/django/tests/modeltests/lookup/ (props changed) pypy/django/tests/modeltests/m2m_and_m2o/ (props changed) pypy/django/tests/modeltests/m2m_intermediary/ (props changed) pypy/django/tests/modeltests/m2m_multiple/ (props changed) pypy/django/tests/modeltests/m2m_recursive/ (props changed) pypy/django/tests/modeltests/m2o_recursive/ (props changed) pypy/django/tests/modeltests/m2o_recursive2/ (props changed) pypy/django/tests/modeltests/manipulators/ (props changed) pypy/django/tests/modeltests/many_to_many/ (props changed) pypy/django/tests/modeltests/many_to_one/ (props changed) pypy/django/tests/modeltests/many_to_one_null/ (props changed) pypy/django/tests/modeltests/model_forms/ (props changed) pypy/django/tests/modeltests/model_inheritance/ (props changed) pypy/django/tests/modeltests/mutually_referential/ (props changed) pypy/django/tests/modeltests/one_to_one/ (props changed) pypy/django/tests/modeltests/or_lookups/ (props changed) pypy/django/tests/modeltests/order_with_respect_to/ (props changed) pypy/django/tests/modeltests/ordering/ (props changed) pypy/django/tests/modeltests/pagination/ (props changed) pypy/django/tests/modeltests/properties/ (props changed) pypy/django/tests/modeltests/reserved_names/ (props changed) pypy/django/tests/modeltests/reverse_lookup/ (props changed) pypy/django/tests/modeltests/save_delete_hooks/ (props changed) pypy/django/tests/modeltests/select_related/ (props changed) pypy/django/tests/modeltests/serializers/ (props changed) pypy/django/tests/modeltests/signals/ (props changed) pypy/django/tests/modeltests/str/ (props changed) pypy/django/tests/modeltests/test_client/ (props changed) pypy/django/tests/modeltests/transactions/ (props changed) pypy/django/tests/modeltests/update/ (props changed) pypy/django/tests/modeltests/user_commands/ (props changed) pypy/django/tests/modeltests/user_commands/management/ (props changed) pypy/django/tests/modeltests/user_commands/management/commands/ (props changed) pypy/django/tests/modeltests/validation/ (props changed) pypy/django/tests/regressiontests/ (props changed) pypy/django/tests/regressiontests/auth_backends/ (props changed) pypy/django/tests/regressiontests/backends/ (props changed) pypy/django/tests/regressiontests/bug639/ (props changed) pypy/django/tests/regressiontests/cache/ (props changed) pypy/django/tests/regressiontests/datastructures/ (props changed) pypy/django/tests/regressiontests/datatypes/ (props changed) pypy/django/tests/regressiontests/dateformat/ (props changed) pypy/django/tests/regressiontests/db_typecasts/ (props changed) pypy/django/tests/regressiontests/decorators/ (props changed) pypy/django/tests/regressiontests/defaultfilters/ (props changed) pypy/django/tests/regressiontests/dispatch/ (props changed) pypy/django/tests/regressiontests/dispatch/tests/ (props changed) pypy/django/tests/regressiontests/fixtures_regress/ (props changed) pypy/django/tests/regressiontests/forms/ (props changed) pypy/django/tests/regressiontests/forms/localflavor/ (props changed) pypy/django/tests/regressiontests/httpwrappers/ (props changed) pypy/django/tests/regressiontests/humanize/ (props changed) pypy/django/tests/regressiontests/i18n/ (props changed) pypy/django/tests/regressiontests/initial_sql_regress/ (props changed) pypy/django/tests/regressiontests/invalid_admin_options/ (props changed) pypy/django/tests/regressiontests/many_to_one_regress/ (props changed) pypy/django/tests/regressiontests/max_lengths/ (props changed) pypy/django/tests/regressiontests/maxlength/ (props changed) pypy/django/tests/regressiontests/middleware/ (props changed) pypy/django/tests/regressiontests/model_fields/ (props changed) pypy/django/tests/regressiontests/model_regress/ (props changed) pypy/django/tests/regressiontests/null_queries/ (props changed) pypy/django/tests/regressiontests/one_to_one_regress/ (props changed) pypy/django/tests/regressiontests/queries/ (props changed) pypy/django/tests/regressiontests/requests/ (props changed) pypy/django/tests/regressiontests/serializers_regress/ (props changed) pypy/django/tests/regressiontests/string_lookup/ (props changed) pypy/django/tests/regressiontests/syndication/ (props changed) pypy/django/tests/regressiontests/templates/ (props changed) pypy/django/tests/regressiontests/test_client_regress/ (props changed) pypy/django/tests/regressiontests/text/ (props changed) pypy/django/tests/regressiontests/urlpatterns_reverse/ (props changed) pypy/django/tests/regressiontests/utils/ (props changed) pypy/django/tests/regressiontests/views/ (props changed) pypy/django/tests/regressiontests/views/media/ (props changed) pypy/django/tests/regressiontests/views/tests/ (props changed) pypy/django/tests/regressiontests/views/tests/generic/ (props changed) Log: fixeol From arigo at codespeak.net Sat May 17 18:14:11 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 17 May 2008 18:14:11 +0200 (CEST) Subject: [pypy-svn] r54858 - pypy/dist/pypy/rlib/rsdl Message-ID: <20080517161411.C89CF16857C@codespeak.net> Author: arigo Date: Sat May 17 18:14:10 2008 New Revision: 54858 Added: pypy/dist/pypy/rlib/rsdl/constants.py (contents, props changed) Modified: pypy/dist/pypy/rlib/rsdl/RSDL.py Log: Export all the constants from SDL (at least, this list contains all the ones that Pygame exports to applications). Modified: pypy/dist/pypy/rlib/rsdl/RSDL.py ============================================================================== --- pypy/dist/pypy/rlib/rsdl/RSDL.py (original) +++ pypy/dist/pypy/rlib/rsdl/RSDL.py Sat May 17 18:14:10 2008 @@ -1,6 +1,7 @@ from pypy.rpython.lltypesystem import lltype, rffi from pypy.rpython.tool import rffi_platform as platform from pypy.translator.tool.cbuild import ExternalCompilationInfo +from pypy.rlib.rsdl.constants import _constants import sys if sys.platform == 'darwin': @@ -33,10 +34,6 @@ Uint16 = platform.SimpleType('Uint16', rffi.INT) Uint32 = platform.SimpleType('Uint32', rffi.INT) - BYTEORDER = platform.ConstantInteger('SDL_BYTEORDER') - BIG_ENDIAN = platform.ConstantInteger('SDL_BIG_ENDIAN') - INIT_VIDEO = platform.ConstantInteger('SDL_INIT_VIDEO') - Rect = platform.Struct('SDL_Rect', [('x', rffi.INT), ('y', rffi.INT), ('w', rffi.INT), @@ -49,6 +46,10 @@ PixelFormat = platform.Struct('SDL_PixelFormat', [('BytesPerPixel', rffi.INT)]) +for _prefix, _list in _constants.items(): + for _name in _list: + setattr(CConfig, _name, platform.ConstantInteger(_prefix+_name)) + globals().update(platform.configure(CConfig)) RectPtr.TO.become(Rect) Added: pypy/dist/pypy/rlib/rsdl/constants.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rlib/rsdl/constants.py Sat May 17 18:14:10 2008 @@ -0,0 +1,253 @@ + +_constants = { + 'SDL_': [ # constants with the 'SDL_' prefix in C + "YV12_OVERLAY", + "IYUV_OVERLAY", + "YUY2_OVERLAY", + "UYVY_OVERLAY", + "YVYU_OVERLAY", + + "SWSURFACE", + "HWSURFACE", + "RESIZABLE", + "ASYNCBLIT", + "OPENGL", + "OPENGLBLIT", + "ANYFORMAT", + "HWPALETTE", + "DOUBLEBUF", + "FULLSCREEN", + "HWACCEL", + "SRCCOLORKEY", + "RLEACCELOK", + "RLEACCEL", + "SRCALPHA", + "PREALLOC", + "NOFRAME", + + "GL_RED_SIZE", + "GL_GREEN_SIZE", + "GL_BLUE_SIZE", + "GL_ALPHA_SIZE", + "GL_BUFFER_SIZE", + "GL_DOUBLEBUFFER", + "GL_DEPTH_SIZE", + "GL_STENCIL_SIZE", + "GL_ACCUM_RED_SIZE", + "GL_ACCUM_GREEN_SIZE", + "GL_ACCUM_BLUE_SIZE", + "GL_ACCUM_ALPHA_SIZE", + "GL_STEREO", #if SDL_VERSION_ATLEAST(1, 2, 5) + "GL_MULTISAMPLEBUFFERS", #if SDL_VERSION_ATLEAST(1, 2, 6) + "GL_MULTISAMPLESAMPLES", #if SDL_VERSION_ATLEAST(1, 2, 6) + + "NOEVENT", + "ACTIVEEVENT", + "KEYDOWN", + "KEYUP", + "MOUSEMOTION", + "MOUSEBUTTONDOWN", + "MOUSEBUTTONUP", + "JOYAXISMOTION", + "JOYBALLMOTION", + "JOYHATMOTION", + "JOYBUTTONDOWN", + "JOYBUTTONUP", + "VIDEORESIZE", + "VIDEOEXPOSE", + "QUIT", + "SYSWMEVENT", + "USEREVENT", + "NUMEVENTS", + + "HAT_CENTERED", + "HAT_UP", + "HAT_RIGHTUP", + "HAT_RIGHT", + "HAT_RIGHTDOWN", + "HAT_DOWN", + "HAT_LEFTDOWN", + "HAT_LEFT", + "HAT_LEFTUP", + + # the following ones are not exposed in Pygame + "INIT_VIDEO", + "BYTEORDER", + "BIG_ENDIAN", + "LIL_ENDIAN", + ], + + '': [ # constants with no prefix in C + "TIMER_RESOLUTION", + "AUDIO_U8", + "AUDIO_S8", + "AUDIO_U16LSB", + "AUDIO_S16LSB", + "AUDIO_U16MSB", + "AUDIO_S16MSB", + "AUDIO_U16", + "AUDIO_S16", + "AUDIO_U16SYS", + "AUDIO_S16SYS", + + "KMOD_NONE", + "KMOD_LSHIFT", + "KMOD_RSHIFT", + "KMOD_LCTRL", + "KMOD_RCTRL", + "KMOD_LALT", + "KMOD_RALT", + "KMOD_LMETA", + "KMOD_RMETA", + "KMOD_NUM", + "KMOD_CAPS", + "KMOD_MODE", + + "KMOD_CTRL", + "KMOD_SHIFT", + "KMOD_ALT", + "KMOD_META", + ], + + 'SDL': [ # constants with the 'SDL' prefix in C + "K_UNKNOWN", + "K_FIRST", + "K_BACKSPACE", + "K_TAB", + "K_CLEAR", + "K_RETURN", + "K_PAUSE", + "K_ESCAPE", + "K_SPACE", + "K_EXCLAIM", + "K_QUOTEDBL", + "K_HASH", + "K_DOLLAR", + "K_AMPERSAND", + "K_QUOTE", + "K_LEFTPAREN", + "K_RIGHTPAREN", + "K_ASTERISK", + "K_PLUS", + "K_COMMA", + "K_MINUS", + "K_PERIOD", + "K_SLASH", + "K_0", + "K_1", + "K_2", + "K_3", + "K_4", + "K_5", + "K_6", + "K_7", + "K_8", + "K_9", + "K_COLON", + "K_SEMICOLON", + "K_LESS", + "K_EQUALS", + "K_GREATER", + "K_QUESTION", + "K_AT", + "K_LEFTBRACKET", + "K_BACKSLASH", + "K_RIGHTBRACKET", + "K_CARET", + "K_UNDERSCORE", + "K_BACKQUOTE", + "K_a", + "K_b", + "K_c", + "K_d", + "K_e", + "K_f", + "K_g", + "K_h", + "K_i", + "K_j", + "K_k", + "K_l", + "K_m", + "K_n", + "K_o", + "K_p", + "K_q", + "K_r", + "K_s", + "K_t", + "K_u", + "K_v", + "K_w", + "K_x", + "K_y", + "K_z", + "K_DELETE", + + "K_KP0", + "K_KP1", + "K_KP2", + "K_KP3", + "K_KP4", + "K_KP5", + "K_KP6", + "K_KP7", + "K_KP8", + "K_KP9", + "K_KP_PERIOD", + "K_KP_DIVIDE", + "K_KP_MULTIPLY", + "K_KP_MINUS", + "K_KP_PLUS", + "K_KP_ENTER", + "K_KP_EQUALS", + "K_UP", + "K_DOWN", + "K_RIGHT", + "K_LEFT", + "K_INSERT", + "K_HOME", + "K_END", + "K_PAGEUP", + "K_PAGEDOWN", + "K_F1", + "K_F2", + "K_F3", + "K_F4", + "K_F5", + "K_F6", + "K_F7", + "K_F8", + "K_F9", + "K_F10", + "K_F11", + "K_F12", + "K_F13", + "K_F14", + "K_F15", + + "K_NUMLOCK", + "K_CAPSLOCK", + "K_SCROLLOCK", + "K_RSHIFT", + "K_LSHIFT", + "K_RCTRL", + "K_LCTRL", + "K_RALT", + "K_LALT", + "K_RMETA", + "K_LMETA", + "K_LSUPER", + "K_RSUPER", + "K_MODE", + + "K_HELP", + "K_PRINT", + "K_SYSREQ", + "K_BREAK", + "K_MENU", + "K_POWER", + "K_EURO", + "K_LAST", + ], + } From cami at codespeak.net Sat May 17 18:19:32 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Sat, 17 May 2008 18:19:32 +0200 (CEST) Subject: [pypy-svn] r54859 - in pypy/branch/gameboy-emulator/pypy/lang/gameboy: . test Message-ID: <20080517161932.33CC0169DB1@codespeak.net> Author: cami Date: Sat May 17 18:19:31 2008 New Revision: 54859 Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/interrupt.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/joypad.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/ram.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/serial.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cartridge.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/timer.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/video.py Log: change inhertence of most gameboy elements Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py Sat May 17 18:19:31 2008 @@ -5,6 +5,8 @@ from pypy.lang.gameboy.timer import * from pypy.rlib.streamio import open_file_as_stream +from pypy.lang.gameboy.ram import iMemory + import os def has_cartridge_battery(self, cartridge_type): @@ -27,11 +29,18 @@ class InvalidMemoryBankTypeError(Exception): pass - - -def map_to_byte(value): - return ord(value) & 0xFF - +def map_to_byte( string): + mapped = [0]*len(string) + for i in range(len(string)): + mapped[i] = ord(string[i]) & 0xFF + return mapped + +def map_to_string(int_array): + mapped = [0]*len(int_array) + for i in range(len(int_array)): + mapped[i] = chr(int_array[i]) + return ("").join(mapped) + # ============================================================================== # CARTRIDGE @@ -60,13 +69,14 @@ self.check_rom() self.create_ram() self.load_battery() - self.mbc = self.create_bank_controller(self.get_memory_bank_type(), self.rom, self.ram, self.clock) + self.mbc = self.create_bank_controller(self.get_memory_bank_type(), \ + self.rom, self.ram, self.clock) def check_rom(self): if not self.verify_header(): - raise Exeption("Cartridge header is corrupted") + raise Exception("Cartridge header is corrupted") if self.cartridge.get_size() < self.get_rom_size(): - raise Exeption("Cartridge is truncated") + raise Exception("Cartridge is truncated") def create_ram(self): ramSize = self.get_ram_size() @@ -152,32 +162,31 @@ self.load(file) def reset(self): - self.cartridge_name = None - self.cartridge_file_path = None - self.cartridge_stream = None - self.cartridge_file_contents = None - self.battery_name = None - self.battery_file_path = None + self.cartridge_name = "" + self.cartridge_file_path = "" + self.cartridge_stream = None + self.cartridge_file_contents = None + self.battery_name = "" + self.battery_file_path = "" self.battery_stream = None self.battery_file_contents = None def load(self, cartridge_path): + if cartridge_path is None: + raise Exception("cartridge_path cannot be None!") cartridge_path = str(cartridge_path) self.cartridge_file_path = cartridge_path - self.cartridge_name = os.path.basename(self.cartridge_file_path) - #FIXED open_file_as_stream self.cartridge_stream = open_file_as_stream(cartridge_path) - self.cartridge_file_contents = map(map_to_byte, \ - self.cartridge_stream.readall()) + self.cartridge_file_contents = map_to_byte( \ + self.cartridge_stream.readall()) self.load_battery(cartridge_path) def load_battery(self, cartridge_file_path): self.battery_file_path = self.create_battery_file_path(cartridge_file_path) - self.battery_name = os.path.basename(self.battery_file_path) if self.has_battery(): self.battery_stream = open_file_as_stream(self.battery_file_path) - self.battery_file_contents = map(map_to_byte, \ + self.battery_file_contents = map_to_byte( \ self.battery_stream.readall()) def create_battery_file_path(self, cartridge_file_path): @@ -194,6 +203,8 @@ return cartridge_file_path + constants.BATTERY_FILE_EXTENSION def has_battery(self): + if self.battery_file_path is None: + return False return os.path.exists(self.battery_file_path) def read(self): @@ -204,24 +215,28 @@ def write_battery(self, ram): output_stream = open_file_as_stream(self.battery_file_path, "w") - output_stream.write(("").join(map(chr, ram))) + output_stream.write(map_to_string(ram)) output_stream.flush() self.battery_file_contents = ram def remove_battery(self): - if self.has_battery(): + if self.has_battery() and self.battery_file_path is not None: os.remove(self.battery_file_path) def get_size(self): + if self.cartridge_file_path is None: + return -1 return os.path.getsize(self.cartridge_file_path) def get_battery_size(self): + if self.battery_file_path is None: + return -1 return os.path.getsize(self.battery_file_path) # ============================================================================== # CARTRIDGE TYPES -class MBC(object): +class MBC(iMemory): def __init__(self, rom, ram, clock_driver): self.set_rom(rom) @@ -408,14 +423,14 @@ 4000-7FFF ROM Bank 1-127 (16KB) A000-BFFF RAM Bank 0-3 (8KB) """ - def __init__(self, rom, ram, clock): + def __init__(self, rom, ram, clock_driver): self.reset() self.min_ram_bank_size = 0 self.max_ram_bank_size = 4 self.min_rom_bank_size = 2 self.max_rom_bank_size = 128 - self.clock = clock + self.clock = clock_driver self.clockLDaysclockLControl = None MBC.__init__(self, rom, ram, clock_driver) @@ -553,14 +568,15 @@ 4000-7FFF ROM Bank 1-511 (16KB) A000-BFFF RAM Bank 0-15 (8KB) """ - def __init__(self, rom, ram, clock_driver, rumble): + def __init__(self, rom, ram, clock_driver): + self.reset() self.min_ram_bank_size = 0 self.max_ram_bank_size = 16 self.min_rom_bank_size = 2 self.max_rom_bank_size = 512 - self.rumble = rumble + self.rumble = rumble = True MBC.__init__(self, rom, ram, clock_driver) @@ -611,13 +627,13 @@ 4000-7FFF ROM Bank 1-127 (16KB) A000-BFFF RAM Bank 0-15 (8KB) """ - def __init__(self, rom, ram, clock): + def __init__(self, rom, ram, clock_driver): self.reset() self.min_ram_bank_size = 0 self.max_ram_bank_size = 4 self.min_rom_bank_size = 2 self.max_rom_bank_size = 128 - self.clock = clock + self.clock = clock_driver self.clock_register = 0 self.clock_shift = 0 self.clock_time = 0 Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py Sat May 17 18:19:31 2008 @@ -373,7 +373,7 @@ return (hi << 8) + lo def fetch_double_register(self, register): - self.pop_double_register(CPU.fetch, register) + self.double_register_inverse_call(CPU.fetch, register) def push(self, data, use_cycles=True): # Stack, 2 cycles @@ -392,11 +392,11 @@ self.cycles += 1 return data - def pop_double_register(self, getter, register=None): + def pop_double_register(self, register): # 3 cycles - if register is None: - register = getter - getter = CPU.pop + self.double_register_inverse_call(CPU.pop, register) + + def double_register_inverse_call(self, getter, register): b = getter(self) # 1 cycle a = getter(self) # 1 cycle register.set(a, b) # 2 cycles @@ -471,16 +471,18 @@ def subtract_a(self, getter, setter=None): # 1 cycle - self.compare_a(getter, setter) # 1 cycle + self.compare_a(getter) # 1 cycle self.a.sub(getter(use_cycles=False), False) def fetch_subtract_a(self): data = self.fetch() - self.subtract_a(lambda use_cycles=False: data) + # 1 cycle + self.compare_a(lambda use_cycles=False: data) # 1 cycle + self.a.sub(data, False) def compare_a(self, getter, setter=None): # 1 cycle - s = (self.a.get() - getter()) & 0xFF + s = int(self.a.get() - getter()) & 0xFF self.f.reset() self.f.n_flag = True self.f.z_flag_compare(s) @@ -1021,12 +1023,12 @@ FLAG_REGISTER_SET = [CPU.is_not_z, CPU.is_z, CPU.is_not_c, CPU.is_c] REGISTER_OP_CODES = [ (0x01, 0x10, CPU.fetch_double_register, REGISTER_SET_A), - (0x09, 0x10, CPU.add_hl, REGISTER_SET_A), + (0x09, 0x10, CPU.add_hl, REGISTER_SET_A), (0x03, 0x10, CPU.inc_double_register, REGISTER_SET_A), (0x0B, 0x10, CPU.dec_double_register, REGISTER_SET_A), - (0xC0, 0x08, CPU.conditional_return, FLAG_REGISTER_SET), - (0xC2, 0x08, CPU.conditional_jump, FLAG_REGISTER_SET), - (0xC4, 0x08, CPU.conditional_call, FLAG_REGISTER_SET), + (0xC0, 0x08, CPU.conditional_return, FLAG_REGISTER_SET), + (0xC2, 0x08, CPU.conditional_jump, FLAG_REGISTER_SET), + (0xC4, 0x08, CPU.conditional_call, FLAG_REGISTER_SET), (0x20, 0x08, CPU.relative_conditional_jump, FLAG_REGISTER_SET), (0xC1, 0x10, CPU.pop_double_register, REGISTER_SET_B), (0xC5, 0x10, CPU.push_double_register, REGISTER_SET_B) Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/interrupt.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/interrupt.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/interrupt.py Sat May 17 18:19:31 2008 @@ -1,4 +1,5 @@ from pypy.lang.gameboy import constants +from pypy.lang.gameboy.ram import iMemory class InterruptFlag(object): @@ -19,7 +20,7 @@ self._is_pending = _is_pending -class Interrupt(object): +class Interrupt(iMemory): """ PyBoy GameBoy (TM) Emulator Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/joypad.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/joypad.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/joypad.py Sat May 17 18:19:31 2008 @@ -1,8 +1,9 @@ from pypy.lang.gameboy import constants -from pypy.lang.gameboy.interrupt import * +from pypy.lang.gameboy.interrupt import Interrupt +from pypy.lang.gameboy.ram import iMemory -class Joypad(object): +class Joypad(iMemory): """ PyBoy GameBoy (TM) Emulator Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/ram.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/ram.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/ram.py Sat May 17 18:19:31 2008 @@ -6,7 +6,15 @@ from pypy.lang.gameboy import constants -class RAM(object): + +class iMemory(object): + def write(self, address, data): + pass + + def read(self, address): + return 0xFF + +class RAM(iMemory): def __init__(self): # Work RAM Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/serial.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/serial.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/serial.py Sat May 17 18:19:31 2008 @@ -1,8 +1,9 @@ from pypy.lang.gameboy import constants from pypy.lang.gameboy.interrupt import * +from pypy.lang.gameboy.ram import iMemory -class Serial(object): +class Serial(iMemory): """ PyBoy GameBoy (TM) Emulator Serial Link Controller Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py Sat May 17 18:19:31 2008 @@ -5,7 +5,8 @@ """ from pypy.lang.gameboy import constants - +from pypy.lang.gameboy.ram import iMemory + class Channel(object): audio_index = 0 @@ -495,7 +496,7 @@ # ------------------------------------------------------------------------------ -class Sound(object): +class Sound(iMemory): def __init__(self, sound_driver): self.buffer = [0] * 512 Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cartridge.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cartridge.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cartridge.py Sat May 17 18:19:31 2008 @@ -44,11 +44,11 @@ def test_cartridge_init(): cartridge = get_cartridge() - assert cartridge.cartridge_name is None + assert cartridge.cartridge_name is "" assert cartridge.cartridge_stream is None assert cartridge.cartridge_file_contents is None - assert cartridge.battery_name is None + assert cartridge.battery_name is "" assert cartridge.battery_stream is None assert cartridge.battery_file_contents is None Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/timer.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/timer.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/timer.py Sat May 17 18:19:31 2008 @@ -7,8 +7,10 @@ from pypy.lang.gameboy import constants from pypy.lang.gameboy.interrupt import * from math import ceil +from pypy.lang.gameboy.ram import iMemory -class Timer(object): + +class Timer(iMemory): def __init__(self, interrupt): assert isinstance(interrupt, Interrupt) Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/video.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/video.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/video.py Sat May 17 18:19:31 2008 @@ -4,9 +4,9 @@ """ from pypy.lang.gameboy import constants +from pypy.lang.gameboy.ram import iMemory - -class Video(object): +class Video(iMemory): #frames = 0 #frame_skip = 0 From cami at codespeak.net Sat May 17 18:24:34 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Sat, 17 May 2008 18:24:34 +0200 (CEST) Subject: [pypy-svn] r54860 - pypy/branch/gameboy-emulator/pypy/lang/gameboy Message-ID: <20080517162434.DFB91168560@codespeak.net> Author: cami Date: Sat May 17 18:24:34 2008 New Revision: 54860 Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py Log: got rid of inline lambda Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py Sat May 17 18:24:34 2008 @@ -477,12 +477,15 @@ def fetch_subtract_a(self): data = self.fetch() # 1 cycle - self.compare_a(lambda use_cycles=False: data) # 1 cycle + self.compare_a_simple(data) # 1 cycle self.a.sub(data, False) def compare_a(self, getter, setter=None): # 1 cycle - s = int(self.a.get() - getter()) & 0xFF + self.compare_a_simple(int(self.a.get() - getter())) + + def compare_a_simple(self, s): + s = s & 0xFF self.f.reset() self.f.n_flag = True self.f.z_flag_compare(s) From arigo at codespeak.net Sat May 17 18:29:26 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 17 May 2008 18:29:26 +0200 (CEST) Subject: [pypy-svn] r54861 - in pypy/dist/pypy/translator/tool: . test Message-ID: <20080517162926.B471B168451@codespeak.net> Author: arigo Date: Sat May 17 18:29:25 2008 New Revision: 54861 Modified: pypy/dist/pypy/translator/tool/cbuild.py pypy/dist/pypy/translator/tool/test/test_cbuild.py Log: Missed the -DMACRO=VALUE case. Modified: pypy/dist/pypy/translator/tool/cbuild.py ============================================================================== --- pypy/dist/pypy/translator/tool/cbuild.py (original) +++ pypy/dist/pypy/translator/tool/cbuild.py Sat May 17 18:29:25 2008 @@ -79,7 +79,12 @@ if arg.startswith('-I'): include_dirs.append(arg[2:]) elif arg.startswith('-D'): - pre_include_lines.append('#define %s 1' % (arg[2:],)) + macro = arg[2:] + if '=' in macro: + macro, value = macro.split('=') + else: + value = '1' + pre_include_lines.append('#define %s %s' % (macro, value)) elif arg.startswith('-L') or arg.startswith('-l'): raise ValueError('linker flag found in compiler options: %r' % (arg,)) Modified: pypy/dist/pypy/translator/tool/test/test_cbuild.py ============================================================================== --- pypy/dist/pypy/translator/tool/test/test_cbuild.py (original) +++ pypy/dist/pypy/translator/tool/test/test_cbuild.py Sat May 17 18:29:25 2008 @@ -127,10 +127,10 @@ def test_from_compiler_flags(self): flags = ('-I/some/include/path -I/other/include/path ' - '-DMACRO1 -D_MACRO2 -?1 -!2') + '-DMACRO1 -D_MACRO2=baz -?1 -!2') eci = ExternalCompilationInfo.from_compiler_flags(flags) assert eci.pre_include_lines == ('#define MACRO1 1', - '#define _MACRO2 1') + '#define _MACRO2 baz') assert eci.includes == () assert eci.include_dirs == ('/some/include/path', '/other/include/path') From cami at codespeak.net Sat May 17 18:40:23 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Sat, 17 May 2008 18:40:23 +0200 (CEST) Subject: [pypy-svn] r54862 - pypy/branch/gameboy-emulator/pypy/lang/gameboy Message-ID: <20080517164023.AABC3168541@codespeak.net> Author: cami Date: Sat May 17 18:40:22 2008 New Revision: 54862 Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py Log: stripped None from DoubleRegister.set Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py Sat May 17 18:40:22 2008 @@ -3,7 +3,12 @@ from pypy.lang.gameboy.ram import * from pypy.lang.gameboy.interrupt import * -class Register(object): + +class iRegister(object): + def get(self, use_cycles=True): + return 0xFF + +class Register(iRegister): def __init__(self, cpu, value=0): assert isinstance(cpu, CPU) @@ -31,7 +36,7 @@ #------------------------------------------------------------------------------ -class DoubleRegister(object): +class DoubleRegister(iRegister): def __init__(self, cpu, hi, lo, reset_value=0): assert isinstance(cpu, CPU) @@ -42,8 +47,8 @@ self.lo = lo self.reset_value = reset_value - def set(self, hi=0, lo=None, use_cycles=True): - if lo is None: + def set(self, hi=0, lo=-1, use_cycles=True): + if lo < 0: self.set_hi(hi >> 8, use_cycles) self.set_lo(hi & 0xFF, use_cycles) if use_cycles: @@ -51,7 +56,7 @@ else: self.set_hi(hi, use_cycles) self.set_lo(lo, use_cycles) - + def reset(self): self.set(self.reset_value, use_cycles=False) @@ -87,7 +92,7 @@ # ------------------------------------------------------------------------------ -class ImmediatePseudoRegister(object): +class ImmediatePseudoRegister(iRegister): def __init__(self, cpu, hl): assert isinstance(cpu, CPU) From cami at codespeak.net Sat May 17 18:43:10 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Sat, 17 May 2008 18:43:10 +0200 (CEST) Subject: [pypy-svn] r54863 - pypy/branch/gameboy-emulator/pypy/lang/gameboy Message-ID: <20080517164310.684E02A017B@codespeak.net> Author: cami Date: Sat May 17 18:43:09 2008 New Revision: 54863 Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py Log: stripped java "super" Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py Sat May 17 18:43:09 2008 @@ -384,7 +384,7 @@ if address > 0xA1FF: return 0xFF else: - return super.read(address) + return MBC.read(sef, address) def write(self, address, data): if address <= 0x1FFF: # 0000-1FFF From arigo at codespeak.net Sat May 17 18:47:30 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 17 May 2008 18:47:30 +0200 (CEST) Subject: [pypy-svn] r54864 - in pypy/dist/pypy/rpython/tool: . test Message-ID: <20080517164730.3168A2A0181@codespeak.net> Author: arigo Date: Sat May 17 18:47:29 2008 New Revision: 54864 Modified: pypy/dist/pypy/rpython/tool/rffi_platform.py pypy/dist/pypy/rpython/tool/test/test_rffi_platform.py Log: Test and fix. Modified: pypy/dist/pypy/rpython/tool/rffi_platform.py ============================================================================== --- pypy/dist/pypy/rpython/tool/rffi_platform.py (original) +++ pypy/dist/pypy/rpython/tool/rffi_platform.py Sat May 17 18:47:29 2008 @@ -100,6 +100,7 @@ name = self.entries[entry] info = self.info[name] self.result[entry] = entry.build_result(info, self) + return self.result[entry] def get_result(self): return dict([(name, self.result[entry]) Modified: pypy/dist/pypy/rpython/tool/test/test_rffi_platform.py ============================================================================== --- pypy/dist/pypy/rpython/tool/test/test_rffi_platform.py (original) +++ pypy/dist/pypy/rpython/tool/test/test_rffi_platform.py Sat May 17 18:47:29 2008 @@ -175,6 +175,29 @@ assert isinstance(c_y, lltype.Struct) assert c_y.c_x is c_x +def test_nested_structs_in_the_opposite_order(): + class CConfig: + _compilation_info_ = ExternalCompilationInfo( + post_include_lines=""" + struct y { + int foo; + unsigned long bar; + }; + struct x { + char c; + struct y y; + }; + """.split("\n")) + y = rffi_platform.Struct("struct y", [("bar", rffi.SHORT)]) + x = rffi_platform.Struct("struct x", [("y", y)]) + + res = rffi_platform.configure(CConfig) + c_x = res["x"] + c_y = res["y"] + assert isinstance(c_x, lltype.Struct) + assert isinstance(c_y, lltype.Struct) + assert c_x.c_y is c_y + def test_array(): dirent = rffi_platform.getstruct("struct dirent", """ From cami at codespeak.net Sat May 17 18:53:15 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Sat, 17 May 2008 18:53:15 +0200 (CEST) Subject: [pypy-svn] r54865 - pypy/branch/gameboy-emulator/pypy/lang/gameboy Message-ID: <20080517165315.1E2152A017B@codespeak.net> Author: cami Date: Sat May 17 18:53:14 2008 New Revision: 54865 Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py Log: changes.. Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py Sat May 17 18:53:14 2008 @@ -384,13 +384,13 @@ if address > 0xA1FF: return 0xFF else: - return MBC.read(sef, address) + return MBC.read(self, address) def write(self, address, data): if address <= 0x1FFF: # 0000-1FFF self.write_ram_enable(address, data) elif address <= 0x3FFF: # 2000-3FFF - self.write_rom_bank() + self.write_rom_bank(address, data) elif address >= 0xA000 and address <= 0xA1FF: # A000-A1FF self.write_ram(address, data) @@ -398,7 +398,7 @@ if (address & 0x0100) == 0: self.ramEnable = ((data & 0x0A) == 0x0A) - def write_rom_bank(self, address): + def write_rom_bank(self, address, data): if (address & 0x0100) == 0: return if (data & 0x0F) == 0: @@ -452,7 +452,7 @@ else: return self.read_clock_data(address) else: - return super.read(address) + return MBC.read(self, address) def read_clock_data(self, address): if self.clock_register == 0x08: @@ -581,7 +581,7 @@ def write(self, address, data): - if address <= write_ram_enable: # 0000-1FFF + if address <= self.write_ram_enable: # 0000-1FFF self.writeRAMEnable(address, data) elif address <= 0x2FFF: # 2000-2FFF self.rom_bank = ((self.rom_bank & (0x01 << 22)) + ((data & 0xFF) << 14)) & self.romSize @@ -663,7 +663,7 @@ if self.ramSize > 0: return self.ram[self.ram_bank + (address & 0x1FFF)] & 0xFF else: - super.read(address) + MBC.read(self, address) def write(self, address, data): if address <= 0x1FFF: # 0000-1FFF From karlb at codespeak.net Sat May 17 19:02:50 2008 From: karlb at codespeak.net (karlb at codespeak.net) Date: Sat, 17 May 2008 19:02:50 +0200 (CEST) Subject: [pypy-svn] r54866 - pypy/dist/pypy/rlib/rsdl Message-ID: <20080517170250.D552F2A017B@codespeak.net> Author: karlb Date: Sat May 17 19:02:47 2008 New Revision: 54866 Added: pypy/dist/pypy/rlib/rsdl/RSDL_helper.py Modified: pypy/dist/pypy/rlib/rsdl/RSDL.py Log: Added RSDL_helper module Modified: pypy/dist/pypy/rlib/rsdl/RSDL.py ============================================================================== --- pypy/dist/pypy/rlib/rsdl/RSDL.py (original) +++ pypy/dist/pypy/rlib/rsdl/RSDL.py Sat May 17 19:02:47 2008 @@ -86,8 +86,11 @@ MapRGB = external('SDL_MapRGB', [PixelFormatPtr, Uint8, Uint8, Uint8], Uint32) GetRGB = external('SDL_GetRGB', [Uint32, PixelFormatPtr, Uint8P, Uint8P, Uint8P], lltype.Void) +GetRGBA = external('SDL_GetRGBA', [Uint32, PixelFormatPtr, + Uint8P, Uint8P, Uint8P, Uint8P], lltype.Void) FillRect = external('SDL_FillRect', [SurfacePtr, RectPtr, Uint32], rffi.INT) BlitSurface = external('SDL_UpperBlit', [SurfacePtr, RectPtr, SurfacePtr, RectPtr], rffi.INT) +SetAlpha = external('SDL_SetAlpha', [SurfacePtr, Uint32, Uint8], rffi.INT) def getpixel(image, x, y): """Return the pixel value at (x, y) Added: pypy/dist/pypy/rlib/rsdl/RSDL_helper.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rlib/rsdl/RSDL_helper.py Sat May 17 19:02:47 2008 @@ -0,0 +1,38 @@ +from pypy.rpython.lltypesystem import lltype, rffi +from pypy.rlib.rsdl import RSDL + +def get_rgb(color, format): + rgb = lltype.malloc(rffi.CArray(RSDL.Uint8), 3, flavor='raw') + try: + RSDL.GetRGB(color, + format, + rffi.ptradd(rgb, 0), + rffi.ptradd(rgb, 1), + rffi.ptradd(rgb, 2)) + r = rffi.cast(lltype.Signed, rgb[0]) + g = rffi.cast(lltype.Signed, rgb[1]) + b = rffi.cast(lltype.Signed, rgb[2]) + result = r, g, b + finally: + lltype.free(rgb, flavor='raw') + + return result + +def get_rgba(color, format): + rgb = lltype.malloc(rffi.CArray(RSDL.Uint8), 4, flavor='raw') + try: + RSDL.GetRGBA(color, + format, + rffi.ptradd(rgb, 0), + rffi.ptradd(rgb, 1), + rffi.ptradd(rgb, 2), + rffi.ptradd(rgb, 3)) + r = rffi.cast(lltype.Signed, rgb[0]) + g = rffi.cast(lltype.Signed, rgb[1]) + b = rffi.cast(lltype.Signed, rgb[2]) + a = rffi.cast(lltype.Signed, rgb[3]) + result = r, g, b, a + finally: + lltype.free(rgb, flavor='raw') + + return result From arigo at codespeak.net Sat May 17 19:04:51 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 17 May 2008 19:04:51 +0200 (CEST) Subject: [pypy-svn] r54867 - in pypy/dist/pypy/rlib/rsdl: . test Message-ID: <20080517170451.559352A017B@codespeak.net> Author: arigo Date: Sat May 17 19:04:49 2008 New Revision: 54867 Modified: pypy/dist/pypy/rlib/rsdl/RSDL.py pypy/dist/pypy/rlib/rsdl/test/test_video.py Log: Event support. Support for keyboard events so far. Modified: pypy/dist/pypy/rlib/rsdl/RSDL.py ============================================================================== --- pypy/dist/pypy/rlib/rsdl/RSDL.py (original) +++ pypy/dist/pypy/rlib/rsdl/RSDL.py Sat May 17 19:04:49 2008 @@ -26,6 +26,8 @@ RectPtr = lltype.Ptr(lltype.ForwardReference()) SurfacePtr = lltype.Ptr(lltype.ForwardReference()) PixelFormatPtr = lltype.Ptr(lltype.ForwardReference()) +EventPtr = lltype.Ptr(lltype.ForwardReference()) +KeyboardEventPtr = lltype.Ptr(lltype.ForwardReference()) class CConfig: _compilation_info_ = eci @@ -46,6 +48,16 @@ PixelFormat = platform.Struct('SDL_PixelFormat', [('BytesPerPixel', rffi.INT)]) + Event = platform.Struct('SDL_Event', [('type', rffi.INT)]) + keysym = platform.Struct('SDL_keysym', [('scancode', rffi.INT), + ('sym', rffi.INT), + ('mod', rffi.INT), + ('unicode', rffi.INT)]) + KeyboardEvent = platform.Struct('SDL_KeyboardEvent', + [('type', rffi.INT), + ('state', rffi.INT), + ('keysym', keysym)]) + for _prefix, _list in _constants.items(): for _name in _list: setattr(CConfig, _name, platform.ConstantInteger(_prefix+_name)) @@ -55,6 +67,8 @@ RectPtr.TO.become(Rect) SurfacePtr.TO.become(Surface) PixelFormatPtr.TO.become(PixelFormat) +EventPtr.TO.become(Event) +KeyboardEventPtr.TO.become(KeyboardEvent) Uint8P = lltype.Ptr(lltype.Array(Uint8, hints={'nolength': True})) Uint16P = lltype.Ptr(lltype.Array(Uint16, hints={'nolength': True})) @@ -73,6 +87,8 @@ SurfacePtr) WM_SetCaption = external('SDL_WM_SetCaption', [rffi.CCHARP, rffi.CCHARP], lltype.Void) +EnableUNICODE = external('SDL_EnableUNICODE', [rffi.INT], rffi.INT) +WaitEvent = external('SDL_WaitEvent', [EventPtr], rffi.INT) Flip = external('SDL_Flip', [SurfacePtr], rffi.INT) CreateRGBSurface = external('SDL_CreateRGBSurface', [Uint32, rffi.INT, rffi.INT, rffi.INT, Modified: pypy/dist/pypy/rlib/rsdl/test/test_video.py ============================================================================== --- pypy/dist/pypy/rlib/rsdl/test/test_video.py (original) +++ pypy/dist/pypy/rlib/rsdl/test/test_video.py Sat May 17 19:04:49 2008 @@ -20,9 +20,10 @@ assert RSDL.Init(RSDL.INIT_VIDEO) >= 0 self.screen = RSDL.SetVideoMode(640, 480, 32, 0) assert self.screen + self.is_interactive = sys.stdout.isatty() def check(self, msg): - if sys.stdout.isatty(): + if self.is_interactive: print answer = raw_input('Interactive test: %s - ok? [Y] ' % msg) if answer and not answer.upper().startswith('Y'): @@ -47,6 +48,34 @@ RSDL.WM_SetCaption("Hello World!", "Hello World!") self.check('The window caption is "Hello World!"') + def test_keypresses(self): + if not self.is_interactive: + py.test.skip("interactive test only") + RSDL.EnableUNICODE(1) + print + print "Keys pressed in the Pygame window should be printed below." + print "Use Escape to quit." + while True: + event = lltype.malloc(RSDL.Event, flavor='raw') + try: + ok = RSDL.WaitEvent(event) + assert rffi.cast(lltype.Signed, ok) == 1 + c_type = rffi.getintfield(event, 'c_type') + if c_type == RSDL.KEYDOWN: + p = rffi.cast(RSDL.KeyboardEventPtr, event) + if rffi.getintfield(p.c_keysym, 'c_sym') == RSDL.K_ESCAPE: + print 'Escape key' + break + char = rffi.getintfield(p.c_keysym, 'c_unicode') + if char != 0: + print 'Key:', unichr(char).encode('utf-8') + else: + print 'Some special key' + else: + print '(event of type %d)' % c_type + finally: + lltype.free(event, flavor='raw') + def test_blit_rect(self): surface = RSDL.CreateRGBSurface(0, 150, 50, 32, r_uint(0x000000FF), From cami at codespeak.net Sat May 17 19:06:46 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Sat, 17 May 2008 19:06:46 +0200 (CEST) Subject: [pypy-svn] r54868 - pypy/branch/gameboy-emulator/pypy/lang/gameboy Message-ID: <20080517170646.0B7472A017B@codespeak.net> Author: cami Date: Sat May 17 19:06:46 2008 New Revision: 54868 Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/timer.py Log: fixed some bugs Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py Sat May 17 19:06:46 2008 @@ -385,7 +385,7 @@ return 0xFF else: return MBC.read(self, address) - + def write(self, address, data): if address <= 0x1FFF: # 0000-1FFF self.write_ram_enable(address, data) @@ -662,8 +662,10 @@ elif self.ram_flag == 0x0A or self.ram_flag == 0x00: if self.ramSize > 0: return self.ram[self.ram_bank + (address & 0x1FFF)] & 0xFF + else: + raise Exception("Invalid Ram Size %i" % self.ramSize) else: - MBC.read(self, address) + return MBC.read(self, address) def write(self, address, data): if address <= 0x1FFF: # 0000-1FFF Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/timer.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/timer.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/timer.py Sat May 17 19:06:46 2008 @@ -102,7 +102,7 @@ if (self.tima < 0) and (self.tima + count >= 0): self.tima = self.tma - count self.interrupt.raise_interrupt(constants.TIMER) - print self.interrupt.timer.is_pending(), self.interrupt.is_pending(constants.TIMER) + #print self.interrupt.timer.is_pending(), self.interrupt.is_pending(constants.TIMER) # CLOCK DRIVER ----------------------------------------------------------------- From arigo at codespeak.net Sat May 17 19:21:54 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 17 May 2008 19:21:54 +0200 (CEST) Subject: [pypy-svn] r54869 - in pypy/dist/pypy/rlib/rsdl: . test Message-ID: <20080517172154.2A0C32A0152@codespeak.net> Author: arigo Date: Sat May 17 19:21:52 2008 New Revision: 54869 Modified: pypy/dist/pypy/rlib/rsdl/RSDL.py pypy/dist/pypy/rlib/rsdl/RSDL_helper.py pypy/dist/pypy/rlib/rsdl/test/test_sdl_image.py Log: Move RSDL.getpixel() to RSDL_helper.get_pixel(). Modified: pypy/dist/pypy/rlib/rsdl/RSDL.py ============================================================================== --- pypy/dist/pypy/rlib/rsdl/RSDL.py (original) +++ pypy/dist/pypy/rlib/rsdl/RSDL.py Sat May 17 19:21:52 2008 @@ -107,31 +107,3 @@ FillRect = external('SDL_FillRect', [SurfacePtr, RectPtr, Uint32], rffi.INT) BlitSurface = external('SDL_UpperBlit', [SurfacePtr, RectPtr, SurfacePtr, RectPtr], rffi.INT) SetAlpha = external('SDL_SetAlpha', [SurfacePtr, Uint32, Uint8], rffi.INT) - -def getpixel(image, x, y): - """Return the pixel value at (x, y) - NOTE: The surface must be locked before calling this! - """ - bpp = rffi.getintfield(image.c_format, 'c_BytesPerPixel') - pitch = rffi.getintfield(image, 'c_pitch') - # Here p is the address to the pixel we want to retrieve - p = rffi.ptradd(image.c_pixels, y * pitch + x * bpp) - if bpp == 1: - return rffi.cast(Uint32, p[0]) - elif bpp == 2: - p = rffi.cast(Uint16P, p) - return rffi.cast(Uint32, p[0]) - elif bpp == 3: - p0 = rffi.cast(lltype.Signed, p[0]) - p1 = rffi.cast(lltype.Signed, p[1]) - p2 = rffi.cast(lltype.Signed, p[2]) - if BYTEORDER == BIG_ENDIAN: - result = p0 << 16 | p1 << 8 | p2 - else: - result = p0 | p1 << 8 | p2 << 16 - return rffi.cast(Uint32, result) - elif bpp == 4: - p = rffi.cast(Uint32P, p) - return p[0] - else: - raise ValueError("bad BytesPerPixel") Modified: pypy/dist/pypy/rlib/rsdl/RSDL_helper.py ============================================================================== --- pypy/dist/pypy/rlib/rsdl/RSDL_helper.py (original) +++ pypy/dist/pypy/rlib/rsdl/RSDL_helper.py Sat May 17 19:21:52 2008 @@ -36,3 +36,31 @@ lltype.free(rgb, flavor='raw') return result + +def get_pixel(image, x, y): + """Return the pixel value at (x, y) + NOTE: The surface must be locked before calling this! + """ + bpp = rffi.getintfield(image.c_format, 'c_BytesPerPixel') + pitch = rffi.getintfield(image, 'c_pitch') + # Here p is the address to the pixel we want to retrieve + p = rffi.ptradd(image.c_pixels, y * pitch + x * bpp) + if bpp == 1: + return rffi.cast(RSDL.Uint32, p[0]) + elif bpp == 2: + p = rffi.cast(RSDL.Uint16P, p) + return rffi.cast(RSDL.Uint32, p[0]) + elif bpp == 3: + p0 = rffi.cast(lltype.Signed, p[0]) + p1 = rffi.cast(lltype.Signed, p[1]) + p2 = rffi.cast(lltype.Signed, p[2]) + if RSDL.BYTEORDER == RSDL.BIG_ENDIAN: + result = p0 << 16 | p1 << 8 | p2 + else: + result = p0 | p1 << 8 | p2 << 16 + return rffi.cast(RSDL.Uint32, result) + elif bpp == 4: + p = rffi.cast(RSDL.Uint32P, p) + return p[0] + else: + raise ValueError("bad BytesPerPixel") Modified: pypy/dist/pypy/rlib/rsdl/test/test_sdl_image.py ============================================================================== --- pypy/dist/pypy/rlib/rsdl/test/test_sdl_image.py (original) +++ pypy/dist/pypy/rlib/rsdl/test/test_sdl_image.py Sat May 17 19:21:52 2008 @@ -1,6 +1,6 @@ import py, os import autopath -from pypy.rlib.rsdl import RSDL, RIMG +from pypy.rlib.rsdl import RSDL, RIMG, RSDL_helper from pypy.rpython.lltypesystem import lltype, rffi @@ -24,7 +24,7 @@ try: for y in range(23): for x in range(y % 13, 17, 13): - color = RSDL.getpixel(image, x, y) + color = RSDL_helper.get_pixel(image, x, y) RSDL.GetRGB(color, image.c_format, rffi.ptradd(rgb, 0), From tverwaes at codespeak.net Sat May 17 19:22:46 2008 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Sat, 17 May 2008 19:22:46 +0200 (CEST) Subject: [pypy-svn] r54870 - in pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk: . test Message-ID: <20080517172246.9B2172A017B@codespeak.net> Author: tverwaes Date: Sat May 17 19:22:45 2008 New Revision: 54870 Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/constants.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/interpreter.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_shadow.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/wrapper.py Log: moving AssociationShadow to associationwrapper Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/constants.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/constants.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/constants.py Sat May 17 19:22:45 2008 @@ -15,18 +15,6 @@ CLASS_FORMAT_INDEX = 2 CLASS_NAME_INDEX = 6 # in the mini.image, at least -# Process < Link -PROCESS_SUSPENDED_CONTEXT_INDEX = 1 -PROCESS_PRIORITY_INDEX = 2 -PROCESS_MY_LIST_INDEX = 3 - -# LinkedList -FIRST_LINK_INDEX = 0 -LAST_LINK_INDEX = 1 - -# Semaphore < LinkedList -EXCESS_SIGNALS_INDEX = 2 - # Scheduler SCHEDULER_PROCESS_LISTS_INDEX = 0 SCHEDULER_ACTIVE_PROCESS_INDEX = 1 @@ -41,10 +29,6 @@ MESSAGE_ARGUMENTS_INDEX = 1 MESSAGE_LOOKUP_CLASS_INDEX = 2 -# Association -ASSOCIATION_KEY_INDEX = 0 -ASSOCIATION_VALUE_INDEX = 1 - # ContextPart CTXPART_SENDER_INDEX = 0 CTXPART_PC_INDEX = 1 Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/interpreter.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/interpreter.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/interpreter.py Sat May 17 19:22:45 2008 @@ -6,6 +6,7 @@ from pypy.lang.smalltalk.shadow import ContextPartShadow from pypy.lang.smalltalk.conftest import option from pypy.rlib import objectmodel, unroll +from pypy.lang.smalltalk import wrapper class MissingBytecode(Exception): @@ -138,9 +139,8 @@ # named var (the value). index = self.currentBytecode & 31 w_association = self.w_method().getliteral(index) - assert isinstance(w_association, model.W_PointersObject) - s_association = w_association.as_association_get_shadow() - self.push(s_association.value()) + association = wrapper.AssociationWrapper(w_association) + self.push(association.value()) def storeAndPopReceiverVariableBytecode(self, interp): index = self.currentBytecode & 7 @@ -281,9 +281,8 @@ self.push(self.w_method().getliteral(variableIndex)) elif variableType == 3: w_association = self.w_method().getliteral(variableIndex) - assert isinstance(w_association, model.W_PointersObject) - s_association = w_association.as_association_get_shadow() - self.push(s_association.value()) + association = wrapper.AssociationWrapper(w_association) + self.push(association.value()) else: assert 0 @@ -297,9 +296,8 @@ raise IllegalStoreError elif variableType == 3: w_association = self.w_method().getliteral(variableIndex) - assert isinstance(w_association, model.W_PointersObject) - s_association = w_association.as_association_get_shadow() - s_association.store_value(self.top()) + association = wrapper.AssociationWrapper(w_association) + association.store_value(self.top()) def extendedStoreAndPopBytecode(self, interp): self.extendedStoreBytecode(interp) @@ -335,18 +333,16 @@ elif opType == 4: # pushLiteralVariable w_association = self.w_method().getliteral(third) - assert isinstance(w_association, model.W_PointersObject) - s_association = w_association.as_association_get_shadow() - self.push(s_association.value()) + association = wrapper.AssociationWrapper(w_association) + self.push(association.value()) elif opType == 5: self.w_receiver().store(third, self.top()) elif opType == 6: self.w_receiver().store(third, self.pop()) elif opType == 7: w_association = self.w_method().getliteral(third) - assert isinstance(w_association, model.W_PointersObject) - s_association = w_association.as_association_get_shadow() - s_association.store_value(self.top()) + association = wrapper.AssociationWrapper(w_association) + association.store_value(self.top()) def singleExtendedSuperBytecode(self, interp): selector, argcount = self.getExtendedSelectorArgcount() Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py Sat May 17 19:22:45 2008 @@ -298,10 +298,6 @@ from pypy.lang.smalltalk.shadow import SchedulerShadow return self.as_special_get_shadow(SchedulerShadow) - def as_association_get_shadow(self): - from pypy.lang.smalltalk.shadow import AssociationShadow - return self.as_special_get_shadow(AssociationShadow) - def as_blockcontext_get_shadow(self, invalid=True): from pypy.lang.smalltalk.shadow import BlockContextShadow return self.as_special_get_shadow(BlockContextShadow, invalid) @@ -426,15 +422,15 @@ def compiledin(self): if self.w_compiledin is None: + from pypy.lang.smalltalk import wrapper # (Blue book, p 607) All CompiledMethods that contain # extended-super bytecodes have the clain which they are found as # their last literal variable. # Last of the literals is an association with compiledin # as a class w_association = self.literals[-1] - assert isinstance(w_association, W_PointersObject) - s_association = w_association.as_association_get_shadow() - self.w_compiledin = s_association.value() + association = wrapper.AssociationWrapper(w_association) + self.w_compiledin = association.value() return self.w_compiledin def getclass(self): Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_shadow.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_shadow.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_shadow.py Sat May 17 19:22:45 2008 @@ -137,45 +137,20 @@ assert s_object.getbytecode() == 101 assert s_object.s_home() == s_object -def process(w_context=methodcontext(), priority=utility.wrap_int(3)): - w_object = model.W_PointersObject(None, 4) - w_object.store(constants.NEXT_LINK_INDEX, 'foo') - w_object.store(constants.PROCESS_SUSPENDED_CONTEXT_INDEX, w_context) - w_object.store(constants.PROCESS_PRIORITY_INDEX, priority) - w_object.store(constants.PROCESS_MY_LIST_INDEX, 'mli') - return w_object - -def test_process(): - w_context = methodcontext() - w_object = process(w_context) - s_object = w_object.as_process_get_shadow() - assert s_object.next() == 'foo' - assert s_object.priority() == 3 - assert s_object.my_list() == 'mli' - assert s_object.w_suspended_context() == w_context - -def test_association(): - w_object = model.W_PointersObject(None, 2) - w_object.store(constants.ASSOCIATION_KEY_INDEX, 'key') - w_object.store(constants.ASSOCIATION_VALUE_INDEX, 'value') - s_object = w_object.as_association_get_shadow() - assert s_object.key() == 'key' - assert s_object.value() == 'value' - -def test_scheduler(): - w_process = process() - w_pl = model.W_PointersObject(None, 0) - w_object = model.W_PointersObject(None, 2) - w_object.store(constants.SCHEDULER_ACTIVE_PROCESS_INDEX, w_process) - w_object.store(constants.SCHEDULER_PROCESS_LISTS_INDEX, w_pl) - s_object = w_object.as_scheduler_get_shadow() - assert s_object.s_active_process() == w_process.as_process_get_shadow() - assert s_object.process_lists() == w_pl - w_process2 = process() - s_object.store_w_active_process(w_process2) - assert s_object.process_lists() == w_pl - assert s_object.s_active_process() != w_process.as_process_get_shadow() - assert s_object.s_active_process() == w_process2.as_process_get_shadow() +#def test_scheduler(): +# w_process = process() +# w_pl = model.W_PointersObject(None, 0) +# w_object = model.W_PointersObject(None, 2) +# w_object.store(constants.SCHEDULER_ACTIVE_PROCESS_INDEX, w_process) +# w_object.store(constants.SCHEDULER_PROCESS_LISTS_INDEX, w_pl) +# s_object = w_object.as_scheduler_get_shadow() +# assert s_object.s_active_process() == w_process.as_process_get_shadow() +# assert s_object.process_lists() == w_pl +# w_process2 = process() +# s_object.store_w_active_process(w_process2) +# assert s_object.process_lists() == w_pl +# assert s_object.s_active_process() != w_process.as_process_get_shadow() +# assert s_object.s_active_process() == w_process2.as_process_get_shadow() #def test_shadowchanges(): # w_object = model.W_PointersObject(None, 2) Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/wrapper.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/wrapper.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/wrapper.py Sat May 17 19:22:45 2008 @@ -67,10 +67,35 @@ self.store_first_link(w_next) LinkWrapper(w_first).store_next_link(objtable.w_nil) return w_first + +class AssociationWrapper(Wrapper): + key = make_getter(0) + value, store_value = make_getter_setter(1) + ''' -class SemaphoreShadow(LinkedListShadow): - """A shadow for Smalltalk objects that are semaphores - """ +class SchedulerShadow(AbstractShadow): + def __init__(self, w_self, invalid): + AbstractShadow.__init__(self, w_self, invalid) + + def s_active_process(self): + w_v = self.w_self()._vars[constants.SCHEDULER_ACTIVE_PROCESS_INDEX] + assert isinstance(w_v, model.W_PointersObject) + return w_v.as_process_get_shadow() + + def store_w_active_process(self, w_object): + self.w_self()._vars[constants.SCHEDULER_ACTIVE_PROCESS_INDEX] = w_object + + def process_lists(self): + w_v = self.w_self()._vars[constants.SCHEDULER_PROCESS_LISTS_INDEX] + assert isinstance(w_v, model.W_PointersObject) + return w_v + + + +class SemaphoreWrapper(LinkedListWrapper): + + excess_signals, store_excess_signals = make_getter_setter(0) + def __init__(self, w_self, invalid=False): LinkedListShadow.__init__(self, w_self, invalid) @@ -103,53 +128,24 @@ return w_scheduler.as_scheduler_get_shadow() def resume(self, w_process, interp): - s_process = w_process.as_process_get_shadow() - s_scheduler = self.s_scheduler() - s_active_process = s_scheduler.s_active_process() - active_priority = s_active_process.priority() - new_priority = s_process.priority() + process = ProcessWrapper(w_process) + scheduler = self.scheduler() + active_process = scheduler.s_active_process() + active_priority = active_process.priority() + new_priority = process.priority() if new_priority > active_priority: - self.put_to_sleep(s_active_process) - self.transfer_to(s_process, interp) + self.put_to_sleep(active_process) + self.transfer_to(process, interp) else: - self.put_to_sleep(s_process) + self.put_to_sleep(process) def synchronous_signal(self, interp): if self.is_empty_list(): - w_value = self.w_self()._vars[constants.EXCESS_SIGNALS_INDEX] + w_value = self.excess_signals() w_value = utility.wrap_int(utility.unwrap_int(w_value) + 1) - self.w_self()._vars[constants.EXCESS_SIGNALS_INDEX] = w_value + self.store_excess_signals(w_value) else: self.resume(self.remove_first_link_of_list(), interp) -class AssociationShadow(AbstractShadow): - def __init__(self, w_self, invalid): - AbstractShadow.__init__(self, w_self, invalid) - - def key(self): - return self.w_self()._vars[constants.ASSOCIATION_KEY_INDEX] - - def value(self): - return self.w_self()._vars[constants.ASSOCIATION_VALUE_INDEX] - - def store_value(self, w_value): - self.w_self()._vars[constants.ASSOCIATION_VALUE_INDEX] = w_value - -class SchedulerShadow(AbstractShadow): - def __init__(self, w_self, invalid): - AbstractShadow.__init__(self, w_self, invalid) - - def s_active_process(self): - w_v = self.w_self()._vars[constants.SCHEDULER_ACTIVE_PROCESS_INDEX] - assert isinstance(w_v, model.W_PointersObject) - return w_v.as_process_get_shadow() - - def store_w_active_process(self, w_object): - self.w_self()._vars[constants.SCHEDULER_ACTIVE_PROCESS_INDEX] = w_object - - def process_lists(self): - w_v = self.w_self()._vars[constants.SCHEDULER_PROCESS_LISTS_INDEX] - assert isinstance(w_v, model.W_PointersObject) - return w_v - ''' + From afa at codespeak.net Sat May 17 20:32:10 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Sat, 17 May 2008 20:32:10 +0200 (CEST) Subject: [pypy-svn] r54871 - pypy/branch/win32port/pypy/rlib Message-ID: <20080517183210.24D2C16857F@codespeak.net> Author: afa Date: Sat May 17 20:32:07 2008 New Revision: 54871 Modified: pypy/branch/win32port/pypy/rlib/getnameinfo.py Log: Translation fix. _socket is now a working_module on win32. Modified: pypy/branch/win32port/pypy/rlib/getnameinfo.py ============================================================================== --- pypy/branch/win32port/pypy/rlib/getnameinfo.py (original) +++ pypy/branch/win32port/pypy/rlib/getnameinfo.py Sat May 17 20:32:07 2008 @@ -4,7 +4,7 @@ """ from pypy.rlib import _rsocket_rffi as _c from pypy.rlib.rsocket import RSocketError, GAIError -from pypy.rpython.lltypesystem import lltype, rffi, ll_str +from pypy.rpython.lltypesystem import lltype, rffi from pypy.rlib.rarithmetic import r_uint NI_NOFQDN = 0x00000001 @@ -24,7 +24,7 @@ if sp: serv = rffi.charp2str(sp.c_s_name) else: - serv = ll_str.ll_int2dec(r_uint(_c.ntohs(sin_port))) + serv = "%d" % r_uint(_c.ntohs(sin_port)) return serv From afa at codespeak.net Sat May 17 20:47:28 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Sat, 17 May 2008 20:47:28 +0200 (CEST) Subject: [pypy-svn] r54872 - pypy/branch/win32port Message-ID: <20080517184728.9607A169E17@codespeak.net> Author: afa Date: Sat May 17 20:47:27 2008 New Revision: 54872 Modified: pypy/branch/win32port/ (props changed) Log: Initialized merge tracking via "svnmerge" with revisions "1-54849" from http://codespeak.net/svn/pypy/dist From fijal at codespeak.net Sat May 17 21:46:30 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 17 May 2008 21:46:30 +0200 (CEST) Subject: [pypy-svn] r54873 - pypy/dist/pypy/translator/goal Message-ID: <20080517194630.B2F39168565@codespeak.net> Author: fijal Date: Sat May 17 21:46:27 2008 New Revision: 54873 Modified: pypy/dist/pypy/translator/goal/translate.py Log: (fijal, antocuni) Simplify the C backend by accident (we were trying to understand what's going on) Modified: pypy/dist/pypy/translator/goal/translate.py ============================================================================== --- pypy/dist/pypy/translator/goal/translate.py (original) +++ pypy/dist/pypy/translator/goal/translate.py Sat May 17 21:46:27 2008 @@ -55,8 +55,8 @@ IntOption("huge", "Threshold in the number of functions after which " "a local call graph and not a full one is displayed", default=100, cmdline="--huge"), - BoolOption("text", "Don't start the pygame viewer", default=False, - cmdline="--text", negation=False), + BoolOption("view", "Start the pygame viewer", default=False, + cmdline="--view", negation=False), BoolOption("help", "show this help message and exit", default=False, cmdline="-h --help", negation=False), ArbitraryOption("goals", "XXX", @@ -241,7 +241,7 @@ log.event("start debugger...") - if not translateconfig.text: + if translateconfig.view: try: t1 = drv.hint_translator except (NameError, AttributeError): From cami at codespeak.net Sat May 17 21:50:42 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Sat, 17 May 2008 21:50:42 +0200 (CEST) Subject: [pypy-svn] r54874 - pypy/branch/gameboy-emulator/pypy/lang/gameboy Message-ID: <20080517195042.5A5B1168572@codespeak.net> Author: cami Date: Sat May 17 21:50:41 2008 New Revision: 54874 Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/timer.py Log: changed MBC1 constructor to support the ramsize directly without strange initialization order Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py Sat May 17 21:50:41 2008 @@ -238,9 +238,16 @@ class MBC(iMemory): - def __init__(self, rom, ram, clock_driver): + def __init__(self, rom, ram, clock_driver, + min_rom_bank_size=0, max_rom_bank_size=0, + min_ram_bank_size=0, max_ram_bank_size=0): + self.min_rom_bank_size = min_rom_bank_size + self.max_rom_bank_size = max_rom_bank_size + self.min_ram_bank_size = min_ram_bank_size + self.max_ram_bank_size = max_ram_bank_size self.set_rom(rom) self.set_ram(ram) + self.reset() def reset(self): self.rom_bank = constants.ROM_BANK_SIZE @@ -250,10 +257,6 @@ self.ram = [] self.romSize = 0 self.ramSize = 0 - self.min_rom_bank_size = 0 - self.max_rom_bank_size = 0 - self.min_ram_bank_size = 0 - self.max_ram_bank_size = 0 def set_rom(self, buffer): banks = len(buffer) / constants.ROM_BANK_SIZE @@ -275,11 +278,10 @@ if address <= 0x3FFF: # 0000-3FFF return self.rom[address] & 0xFF elif address <= 0x7FFF:# 4000-7FFF - print address, self.rom_bank return self.rom[self.rom_bank + (address & 0x3FFF)] & 0xFF elif address >= 0xA000 and address <= 0xBFFF and self.ramEnable: # A000-BFFF - return self.ram[self.ram_bank + (address & 0x1FFF)] & 0xFF - return 0xFF + return self.ram[self.ram_bank + (address & 0x1FFF)] & 0xFF + raise Exception("Invalid address") def write(self, address, data): pass @@ -291,12 +293,11 @@ class DefaultMBC(MBC): def __init__(self, rom, ram, clock_driver): - self.reset() - self.min_rom_bank_size = 0 - self.max_rom_bank_size = 0xFFFFFF - self.min_ram_bank_size = 0 - self.max_ram_bank_size = 0xFFFFFF - MBC.__init__(self, rom, ram, clock_driver) + MBC.__init__(self, rom, ram, clock_driver, + min_rom_bank_size=0, + max_rom_bank_size=0xFFFFFF, + min_ram_bank_size=0, + max_ram_bank_size=0xFFFFFF) #------------------------------------------------------------------------------- @@ -313,12 +314,11 @@ A000-BFFF RAM Bank 0-3 (8KB) """ def __init__(self, rom, ram, clock_driver): - self.reset() - self.min_ram_bank_size = 0 - self.max_ram_bank_size = 4 - self.min_rom_bank_size = 2 - self.max_rom_bank_size = 128 - MBC.__init__(self, rom, ram, clock_driver) + MBC.__init__(self, rom, ram, clock_driver, + min_ram_bank_size=0, + max_ram_bank_size=4, + min_rom_bank_size=2, + max_rom_bank_size=128) def reset(self): MBC.reset(self) @@ -372,12 +372,11 @@ RAM_BANK_SIZE = 512 def __init__(self, rom, ram, clock_driver): - self.reset() - self.min_ram_bank_size = constants.RAM_BANK_SIZE - self.max_ram_bank_size = constants.RAM_BANK_SIZE - self.min_rom_bank_size = 2 - self.max_rom_bank_size = 16 - MBC.__init__(self, rom, ram, clock_driver) + MBC.__init__(self, rom, ram, clock_driver, + min_ram_bank_size=constants.RAM_BANK_SIZE, + max_ram_bank_size=constants.RAM_BANK_SIZE, + min_rom_bank_size=2, + max_rom_bank_size=16) def read(self, address): @@ -424,30 +423,34 @@ A000-BFFF RAM Bank 0-3 (8KB) """ def __init__(self, rom, ram, clock_driver): - self.reset() - self.min_ram_bank_size = 0 - self.max_ram_bank_size = 4 - self.min_rom_bank_size = 2 - self.max_rom_bank_size = 128 - - self.clock = clock_driver - self.clockLDaysclockLControl = None - - MBC.__init__(self, rom, ram, clock_driver) - self.reset() + MBC.__init__(self, rom, ram, clock_driver, + min_ram_bank_size=0, + max_ram_bank_size=4, + min_rom_bank_size=2, + max_rom_bank_size=128) def reset(self): MBC.reset(self) - self.clock_time = self.clock.get_time() - self.clockLatch = self.clock_register = 0 - self.clockSeconds = self.clockMinutes = self.clockHours = self.clockDays = self.clockControl = 0 - self.clockLSeconds = self.clockLMinutes = self.clockLHours = self.clockLDays = self.clockLControl = 0 + self.clockLDaysclockLControl = None + self.clock_time = self.clock.get_time() + self.clockLatch = 0 + self.clock_register = 0 + self.clockSeconds = 0 + self.clockMinutes = 0 + self.clockHours = 0 + self.clockDays = 0 + self.clockControl = 0 + self.clockLSeconds = 0 + self.clockLMinutes = 0 + self.clockLHours = 0 + self.clockLDays = 0 + self.clockLControl = 0 def read(self, address): - if (address >= 0xA000 and address <= 0xBFFF): # A000-BFFF - if (self.ram_bank >= 0): + if address >= 0xA000 and address <= 0xBFFF: # A000-BFFF + if self.ram_bank >= 0: return self.ram[self.ram_bank + (address & 0x1FFF)] & 0xFF else: return self.read_clock_data(address) @@ -465,6 +468,7 @@ return self.clockLDays if self.clock_register == 0x0C: return self.clockLControl + raise Exception("invalid clockregister %i" % self.clock_register) def write(self, address, data): if address <= 0x1FFF: # 0000-1FFF @@ -569,16 +573,16 @@ A000-BFFF RAM Bank 0-15 (8KB) """ def __init__(self, rom, ram, clock_driver): - - self.reset() - self.min_ram_bank_size = 0 - self.max_ram_bank_size = 16 - self.min_rom_bank_size = 2 - self.max_rom_bank_size = 512 - - self.rumble = rumble = True - MBC.__init__(self, rom, ram, clock_driver) + MBC.__init__(self, rom, ram, clock_driver, + min_ram_bank_size=0, + max_ram_bank_size=16, + min_rom_bank_size=2, + max_rom_bank_size=512) + def reset(self): + MBC.reset(self) + self.rumble = True + def write(self, address, data): if address <= self.write_ram_enable: # 0000-1FFF @@ -628,20 +632,11 @@ A000-BFFF RAM Bank 0-15 (8KB) """ def __init__(self, rom, ram, clock_driver): - self.reset() - self.min_ram_bank_size = 0 - self.max_ram_bank_size = 4 - self.min_rom_bank_size = 2 - self.max_rom_bank_size = 128 - self.clock = clock_driver - self.clock_register = 0 - self.clock_shift = 0 - self.clock_time = 0 - self.set_rom(rom) - self.set_ram(ram) - self.ram_flag = 0 - self.ram_value = 0 - MBC.__init__(self, rom, ram, clock_driver) + MBC.__init__(self, rom, ram, clock_driver, + min_ram_bank_size=0, + max_ram_bank_size=4, + min_rom_bank_size=2, + max_rom_bank_size=128) def reset(self): @@ -662,8 +657,7 @@ elif self.ram_flag == 0x0A or self.ram_flag == 0x00: if self.ramSize > 0: return self.ram[self.ram_bank + (address & 0x1FFF)] & 0xFF - else: - raise Exception("Invalid Ram Size %i" % self.ramSize) + raise Exception("Huc3 read error") else: return MBC.read(self, address) Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/timer.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/timer.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/timer.py Sat May 17 21:50:41 2008 @@ -8,6 +8,7 @@ from pypy.lang.gameboy.interrupt import * from math import ceil from pypy.lang.gameboy.ram import iMemory +import time class Timer(iMemory): @@ -112,5 +113,5 @@ pass def get_time(self): - return System.currentTimeMillis() / 1000 + return time.time() From cami at codespeak.net Sat May 17 23:53:21 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Sat, 17 May 2008 23:53:21 +0200 (CEST) Subject: [pypy-svn] r54875 - pypy/branch/gameboy-emulator/pypy/lang/gameboy Message-ID: <20080517215321.53F80398004@codespeak.net> Author: cami Date: Sat May 17 23:53:18 2008 New Revision: 54875 Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/interrupt.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/joypad.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/ram.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/serial.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/timer.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/video.py Log: fixed some missing variables now lovely translator only produces only blocked blocks, thousends of blocked blocks Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py Sat May 17 23:53:18 2008 @@ -79,11 +79,11 @@ raise Exception("Cartridge is truncated") def create_ram(self): - ramSize = self.get_ram_size() + ram_size = self.get_ram_size() if self.get_memory_bank_type() >= constants.TYPE_MBC2 \ and self.get_memory_bank_type() <= constants.TYPE_MBC2_BATTERY: - ramSize = 512 - self.ram = [0xFF]*ramSize + ram_size = 512 + self.ram = [0xFF]*ram_size def load_battery(self): if self.cartridge.has_battery(): @@ -103,9 +103,9 @@ return self.rom def get_rom_size(self): - romSize = self.rom[constants.CARTRIDGE_ROM_SIZE_ADDRESS] & 0xFF - if romSize>=0x00 and romSize<=0x07: - return 32768 << romSize + rom_size = self.rom[constants.CARTRIDGE_ROM_SIZE_ADDRESS] & 0xFF + if rom_size>=0x00 and rom_size<=0x07: + return 32768 << rom_size return -1 def get_ram_size(self): @@ -241,29 +241,30 @@ def __init__(self, rom, ram, clock_driver, min_rom_bank_size=0, max_rom_bank_size=0, min_ram_bank_size=0, max_ram_bank_size=0): + self.clock = clock_driver self.min_rom_bank_size = min_rom_bank_size self.max_rom_bank_size = max_rom_bank_size self.min_ram_bank_size = min_ram_bank_size self.max_ram_bank_size = max_ram_bank_size + self.reset() self.set_rom(rom) self.set_ram(ram) - self.reset() def reset(self): self.rom_bank = constants.ROM_BANK_SIZE self.ram_bank = 0 - self.ramEnable = False + self.ram_enable = False self.rom = [] self.ram = [] - self.romSize = 0 - self.ramSize = 0 + self.rom_size = 0 + self.ram_size = 0 def set_rom(self, buffer): banks = len(buffer) / constants.ROM_BANK_SIZE if banks < self.min_rom_bank_size or banks > self.max_rom_bank_size: raise Exception("Invalid constants.ROM size") self.rom = buffer - self.romSize = constants.ROM_BANK_SIZE*banks - 1 + self.rom_size = constants.ROM_BANK_SIZE*banks - 1 def set_ram(self, buffer): @@ -271,7 +272,7 @@ if banks < self.min_ram_bank_size or banks > self.max_ram_bank_size: raise Exception("Invalid constants.RAM size") self.ram = buffer - self.ramSize = constants.RAM_BANK_SIZE*banks - 1 + self.ram_size = constants.RAM_BANK_SIZE*banks - 1 def read(self, address): @@ -279,7 +280,7 @@ return self.rom[address] & 0xFF elif address <= 0x7FFF:# 4000-7FFF return self.rom[self.rom_bank + (address & 0x3FFF)] & 0xFF - elif address >= 0xA000 and address <= 0xBFFF and self.ramEnable: # A000-BFFF + elif address >= 0xA000 and address <= 0xBFFF and self.ram_enable: # A000-BFFF return self.ram[self.ram_bank + (address & 0x1FFF)] & 0xFF raise Exception("Invalid address") @@ -333,26 +334,26 @@ self.write_rom_bank_2(address, data) elif address <= 0x7FFF: # 6000-7FFF self.memoryModel = data & 0x01 - elif address >= 0xA000 and address <= 0xBFFF and self.ramEnable: # A000-BFFF + elif address >= 0xA000 and address <= 0xBFFF and self.ram_enable: # A000-BFFF self.ram[self.ram_bank + (address & 0x1FFF)] = data def write_ram_enable(self, address, data): - if self.ramSize > 0: - self.ramEnable = ((data & 0x0A) == 0x0A) + if self.ram_size > 0: + self.ram_enable = ((data & 0x0A) == 0x0A) def write_rom_bank_1(self, address, data): if (data & 0x1F) == 0: data = 1 if self.memoryModel == 0: - self.rom_bank = ((self.rom_bank & 0x180000) + ((data & 0x1F) << 14)) & self.romSize + self.rom_bank = ((self.rom_bank & 0x180000) + ((data & 0x1F) << 14)) & self.rom_size else: - self.rom_bank = ((data & 0x1F) << 14) & self.romSize + self.rom_bank = ((data & 0x1F) << 14) & self.rom_size def write_rom_bank_2(self, address, data): if self.memoryModel == 0: - self.rom_bank = ((self.rom_bank & 0x07FFFF) + ((data & 0x03) << 19)) & self.romSize + self.rom_bank = ((self.rom_bank & 0x07FFFF) + ((data & 0x03) << 19)) & self.rom_size else: - self.ram_bank = ((data & 0x03) << 13) & self.ramSize + self.ram_bank = ((data & 0x03) << 13) & self.ram_size #------------------------------------------------------------------------------- @@ -395,17 +396,17 @@ def write_ram_enable(self, address, data): if (address & 0x0100) == 0: - self.ramEnable = ((data & 0x0A) == 0x0A) + self.ram_enable = ((data & 0x0A) == 0x0A) def write_rom_bank(self, address, data): if (address & 0x0100) == 0: return if (data & 0x0F) == 0: data = 1 - self.rom_bank = ((data & 0x0F) << 14) & self.romSize + self.rom_bank = ((data & 0x0F) << 14) & self.rom_size def write_ram(self, address, data): - if self.ramEnable: + if self.ram_enable: self.ram[address & 0x01FF] = data & 0x0F @@ -424,17 +425,17 @@ """ def __init__(self, rom, ram, clock_driver): MBC.__init__(self, rom, ram, clock_driver, - min_ram_bank_size=0, - max_ram_bank_size=4, - min_rom_bank_size=2, - max_rom_bank_size=128) + min_ram_bank_size=0, + max_ram_bank_size=4, + min_rom_bank_size=2, + max_rom_bank_size=128) def reset(self): MBC.reset(self) self.clockLDaysclockLControl = None self.clock_time = self.clock.get_time() - self.clockLatch = 0 + self.clock_latch = 0 self.clock_register = 0 self.clockSeconds = 0 self.clockMinutes = 0 @@ -479,36 +480,36 @@ self.write_ram_bank(address, data) elif address <= 0x7FFF: # 6000-7FFF self.write_clock_latch(address, data) - elif address >= 0xA000 and address <= 0xBFFF and self.ramEnable: # A000-BFFF + elif address >= 0xA000 and address <= 0xBFFF and self.ram_enable: # A000-BFFF self.write_clock_data(address, data) def write_ram_enable(self, address, data): - if self.ramSize > 0: - self.ramEnable = ((data & 0x0A) == 0x0A) + if self.ram_size > 0: + self.ram_enable = ((data & 0x0A) == 0x0A) def write_rom_bank(self, address, data): if data == 0: data = 1 - self.rom_bank = ((data & 0x7F) << 14) & self.romSize + self.rom_bank = ((data & 0x7F) << 14) & self.rom_size def write_ram_bank(self, address, data): if data >= 0x00 and data <= 0x03: - self.ram_bank = (data << 13) & self.ramSize + self.ram_bank = (data << 13) & self.ram_size else: self.ram_bank = -1 self.clock_register = data def write_clock_latch(self, address, data): - if self.clockLatch == 0 and data == 1: - self.latchClock() + if self.clock_latch == 0 and data == 1: + self.latch_clock() if data == 0 or data == 1: - self.clockLatch = data + self.clock_latch = data def write_clock_data(self, address, data): if self.ram_bank >= 0: self.ram[self.ram_bank + (address & 0x1FFF)] = data else: - self.updateClock() + self.update_clock() if self.clock_register == 0x08: self.clockSeconds = data if self.clock_register == 0x09: @@ -522,15 +523,15 @@ def latch_clock(self): - self.updateClock() + self.update_clock() self.clockLSeconds = self.clockSeconds self.clockLMinutes = self.clockMinutes - self.clockLHours = self.clockHours - self.clockLDays = self.clockDays & 0xFF + self.clockLHours = self.clockHours + self.clockLDays = self.clockDays & 0xFF self.clockLControl = (self.clockControl & 0xFE) | ((self.clockDays >> 8) & 0x01) - def update_clock(): + def update_clock(self): now = self.clock.get_time() if (self.clockControl & 0x40) == 0: elapsed = now - self.clock_time @@ -586,25 +587,25 @@ def write(self, address, data): if address <= self.write_ram_enable: # 0000-1FFF - self.writeRAMEnable(address, data) + self.write_ram_enable(address, data) elif address <= 0x2FFF: # 2000-2FFF - self.rom_bank = ((self.rom_bank & (0x01 << 22)) + ((data & 0xFF) << 14)) & self.romSize + self.rom_bank = ((self.rom_bank & (0x01 << 22)) + ((data & 0xFF) << 14)) & self.rom_size elif address <= 0x3FFF: # 3000-3FFF - self.rom_bank = ((self.rom_bank & (0xFF << 14)) + ((data & 0x01) << 22)) & self.romSize + self.rom_bank = ((self.rom_bank & (0xFF << 14)) + ((data & 0x01) << 22)) & self.rom_size elif address <= 0x4FFF: # 4000-4FFF self.write_ram_bank(address, data) - elif address >= 0xA000 and address <= 0xBFFF and self.ramEnable: # A000-BFFF + elif address >= 0xA000 and address <= 0xBFFF and self.ram_enable: # A000-BFFF self.ram[self.ram_bank + (address & 0x1FFF)] = data def write_ram_enable(self, address, data): - if self.ramSize > 0: - self.ramEnable = ((data & 0x0A) == 0x0A) + if self.ram_size > 0: + self.ram_enable = ((data & 0x0A) == 0x0A) def write_ram_bank(self, address, data): if self.rumble: - self.ram_bank = ((data & 0x07) << 13) & self.ramSize + self.ram_bank = ((data & 0x07) << 13) & self.ram_size else: - self.ram_bank = ((data & 0x0F) << 13) & self.ramSize + self.ram_bank = ((data & 0x0F) << 13) & self.ram_size #------------------------------------------------------------------------------- @@ -649,39 +650,41 @@ def read(self, address): + address = int(address) if address >= 0xA000 and address <= 0xBFFF:# A000-BFFF if self.ram_flag == 0x0C: return self.ram_value elif self.ram_flag == 0x0D: return 0x01 elif self.ram_flag == 0x0A or self.ram_flag == 0x00: - if self.ramSize > 0: + if self.ram_size > 0: return self.ram[self.ram_bank + (address & 0x1FFF)] & 0xFF raise Exception("Huc3 read error") else: return MBC.read(self, address) def write(self, address, data): + address = int(address) if address <= 0x1FFF: # 0000-1FFF self.ram_flag = data elif address <= 0x3FFF:# 2000-3FFF self.write_rom_bank(address, data) elif address <= 0x5FFF: # 4000-5FFF - self.ram_bank = ((data & 0x0F) << 13) & self.ramSize + self.ram_bank = ((data & 0x0F) << 13) & self.ram_size elif address >= 0xA000 and address <= 0xBFFF: # A000-BFFF self.write_ram_flag(address, data) def write_rom_bank(self, address, data): if (data & 0x7F) == 0: data = 1 - self.rom_bank = ((data & 0x7F) << 14) & self.romSize + self.rom_bank = ((data & 0x7F) << 14) & self.rom_size def write_ram_flag(self, address, data): if self.ram_flag == 0x0B: self.write_with_ram_flag_0x0B(address, data) elif self.ram_flag >= 0x0C and self.ram_flag <= 0x0E: pass - elif self.ram_flag == 0x0A and self.ramSize > 0: + elif self.ram_flag == 0x0A and self.ram_size > 0: self.ram[self.ram_bank + (address & 0x1FFF)] = data def write_with_ram_flag_0x0B(self, address, data): Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py Sat May 17 23:53:18 2008 @@ -117,6 +117,13 @@ assert isinstance(cpu, CPU) self.cpu = cpu self.reset() + #added for rpython type inference + self.z_flag = False + self.n_flag = False + self.h_flag = False + self.c_flag = False + self.p_flag = False + self.s_flag = False def reset(self, keep_z=False, keep_n=False, keep_h=False, keep_c=False,\ keep_p=False, keep_s=False): @@ -318,6 +325,7 @@ self.rom = banks def emulate(self, ticks): + ticks = int(ticks) self.cycles += ticks self.handle_pending_interrupt() while self.cycles > 0: Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/interrupt.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/interrupt.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/interrupt.py Sat May 17 23:53:18 2008 @@ -74,12 +74,14 @@ self.mask_mapping[mask].set_pending(False) def write(self, address, data): + address = int(address) if address == constants.IE: self.set_interrupt_enable(data) elif address == constants.IF: self.set_fnterrupt_flag(data) def read(self, address): + address = int(address) if address == constants.IE: return self.get_interrupt_enable() elif address == constants.IF: Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/joypad.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/joypad.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/joypad.py Sat May 17 23:53:18 2008 @@ -26,6 +26,7 @@ return self.cycles def emulate(self, ticks): + ticks = int(ticks) self.cycles -= ticks if self.cycles <= 0: if self.driver.is_raised(): @@ -33,11 +34,13 @@ self.cycles = constants.JOYPAD_CLOCK def write(self, address, data): + address = int(address) if address == constants.JOYP: self.joyp = (self.joyp & 0xC) + (data & 0x3) self.update() def read(self, address): + address = int(address) if address == constants.JOYP: return (self.joyp << 4) + self.button_code return 0xFF Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/ram.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/ram.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/ram.py Sat May 17 23:53:18 2008 @@ -30,20 +30,22 @@ self.h_ram = [0x00]*128 def write(self, address, data): - if (address >= 0xC000 and address <= 0xFDFF): + address = int(address) + if address >= 0xC000 and address <= 0xFDFF: # C000-DFFF Work RAM (8KB) # E000-FDFF Echo RAM self.w_ram[address & 0x1FFF] = data - elif (address >= 0xFF80 and address <= 0xFFFE): + elif address >= 0xFF80 and address <= 0xFFFE: # FF80-FFFE High RAM self.h_ram[address & 0x7F] = data def read(self, address): - if (address >= 0xC000 and address <= 0xFDFF): + address = int(address) + if address >= 0xC000 and address <= 0xFDFF: # C000-DFFF Work RAM # E000-FDFF Echo RAM return self.w_ram[address & 0x1FFF] & 0xFF - elif (address >= 0xFF80 and address <= 0xFFFE): + elif address >= 0xFF80 and address <= 0xFFFE: # FF80-FFFE High RAM return self.h_ram[address & 0x7F] & 0xFF return 0xFF Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/serial.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/serial.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/serial.py Sat May 17 23:53:18 2008 @@ -23,6 +23,7 @@ return self.cycles def emulate(self, ticks): + ticks = int(ticks) if (self.sc & 0x81) != 0x81: return self.cycles -= ticks @@ -47,12 +48,14 @@ return self.sc def write(self, address, data): + address = int(address) if address == constants.SB: self.set_serial_data(data) elif address == constants.SC: self.set_serial_control(data) def read(self, address): + address = int(address) if address == constants.SB: return self.get_serial_data() elif address == constants.SC: Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py Sat May 17 23:53:18 2008 @@ -126,14 +126,14 @@ if self.sample_sweep_length > 0: self.sample_sweep_length-=1 if self.sample_sweep_length <= 0: - sweepSteps = (self.sample_sweep & 0x07) - if sweepSteps != 0: + sweep_steps = (self.sample_sweep & 0x07) + if sweep_steps != 0: frequency = ((self.audio_playback & 0x07) << 8) + \ self.audio_frequency if (self.sample_sweep & 0x08) != 0: - frequency -= frequency >> sweepSteps + frequency -= frequency >> sweep_steps else: - frequency += frequency >> sweepSteps + frequency += frequency >> sweep_steps if frequency < 2048: self.audio_1_frequency = self.frequency_table[frequency] self.audio_frequency = frequency & 0xFF @@ -146,17 +146,10 @@ ((self.sample_sweep >> 4) & 0x07) def mix_audio(self, buffer, length): - wave_patter = 0x18 - if (self.audio_length & 0xC0) == 0x00: - wave_patter = 0x04 - elif (self.audio_length & 0xC0) == 0x40: - wave_patter = 0x08 - elif (self.audio_length & 0xC0) == 0x80: - wave_patter = 0x10 - wave_patter << 22 + wave_pattern = self.get_current_wave_pattern() for index in range(0, length, 3): self.audio_1_index += self.audio_1_frequency - if (self.audio_1_index & (0x1F << 22)) >= wave_patter: + if (self.audio_1_index & (0x1F << 22)) >= wave_pattern: if (self.output_terminal & 0x10) != 0: buffer[index + 0] -= self.audio_volume if (self.output_terminal & 0x01) != 0: @@ -167,6 +160,17 @@ if (self.output_terminal & 0x01) != 0: buffer[index + 1] += self.audio_volume + def get_current_wave_pattern(self): + wave_pattern = 0x18 + if (self.audio_length & 0xC0) == 0x00: + wave_pattern = 0x04 + elif (self.audio_length & 0xC0) == 0x40: + wave_pattern = 0x08 + elif (self.audio_length & 0xC0) == 0x80: + wave_pattern = 0x10 + return wave_pattern << 22 + + #SquareWaveGenerator @@ -233,17 +237,10 @@ (self.audio_envelope & 0x07) def mix_audio(self, buffer, length): - wave_patter = 0x18 - if (self.audio_length & 0xC0) == 0x00: - wave_patter = 0x04 - elif (self.audio_length & 0xC0) == 0x40: - wave_patter = 0x08 - elif (self.audio_length & 0xC0) == 0x80: - wave_patter = 0x10 - wave_patter << 22 + wave_pattern = self.get_current_wave_pattern() for index in range(0, length): self.audio_2_index += self.audio_2_frequency - if ((self.audio_2_index & (0x1F << 22)) >= wave_patter): + if ((self.audio_2_index & (0x1F << 22)) >= wave_pattern): if ((self.output_terminal & 0x20) != 0): buffer[index + 0] -= self.audio_volume if ((self.output_terminal & 0x02) != 0): @@ -254,7 +251,15 @@ if ((self.output_terminal & 0x02) != 0): buffer[index + 1] += self.audio_volume - + def get_current_wave_pattern(self): + wave_pattern = 0x18 + if (self.audio_length & 0xC0) == 0x00: + wave_pattern = 0x04 + elif (self.audio_length & 0xC0) == 0x40: + wave_pattern = 0x08 + elif (self.audio_length & 0xC0) == 0x80: + wave_pattern = 0x10 + return wave_pattern << 22 @@ -321,13 +326,7 @@ self.output_enable &= ~0x04 def mix_audio(self, buffer, length): - wave_patter = 2 - if (self.audio_level & 0x60) == 0x00: - wave_patter = 8 - elif (self.audio_level & 0x60) == 0x40: - wave_patter = 0 - elif (self.audio_level & 0x60) == 0x80: - wave_patter = 1 + wave_pattern = self.get_current_wave_pattern() for index in range(0, length, 2): self.audio_3_index += self.audio_3_frequency sample = self.audio_wave_pattern[(self.audio_3_index >> 23) & 0x0F] @@ -335,15 +334,22 @@ sample = (sample >> 0) & 0x0F else: sample = (sample >> 4) & 0x0F - - sample = ((sample - 8) << 1) >> level - + sample = int(((sample - 8) << 1) >> self.audio_level) if (self.output_terminal & 0x40) != 0: buffer[index + 0] += sample if (self.output_terminal & 0x04) != 0: buffer[index + 1] += sample - + def get_current_wave_pattern(self): + wave_pattern = 2 + if (self.audio_level & 0x60) == 0x00: + wave_pattern = 8 + elif (self.audio_level & 0x60) == 0x40: + wave_pattern = 0 + elif (self.audio_level & 0x60) == 0x80: + wave_pattern = 1 + return wave_pattern + class NoiseGenerator(Channel): @@ -469,7 +475,7 @@ def mix_audio(self, buffer, length): for index in range(0, length, 2): self.audio_4_index += self.audio_4_frequency - polynomial + #polynomial if (self.audio_polynomial & 0x08) != 0: # 7 steps self.audio_4_index &= 0x7FFFFF @@ -585,10 +591,11 @@ return self.cycles def emulate(self, ticks): + ticks = int(ticks) self.cycles -= ticks while (self.cycles <= 0): self.update_audio() - if self.driver.isEnabled(): + if self.driver.is_enabled(): self.mix_down_audio() self.cycles += constants.GAMEBOY_CLOCK / constants.SOUND_CLOCK @@ -600,6 +607,7 @@ self.frames %= constants.SOUND_CLOCK def read(self, address): + address = int(address) if address==constants.NR10: return self.channel1.get_audio_sweep() elif address == constants.NR11: @@ -653,6 +661,7 @@ return 0xFF def write(self, address, data): + address = int(address) if address==constants.NR10: self.channel1.set_audio_sweep(data) elif address == constants.NR11: Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/timer.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/timer.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/timer.py Sat May 17 23:53:18 2008 @@ -19,29 +19,34 @@ self.reset() def reset(self): - self.div = 0 + self.div = 0 self.divider_cycles = constants.DIV_CLOCK - self.tima = self.tma = self.tac = 0x00 - self.timer_cycles = self.timer_clock = constants.TIMER_CLOCK[0] + self.tima = 0 + self.tma = 0 + self.tac = 0x00 + self.timer_cycles = constants.TIMER_CLOCK[0] + self.timer_clock = constants.TIMER_CLOCK[0] def write(self, address, data): - if address==constants.DIV: + address = int(address) + if address == constants.DIV: self.set_divider(data) - elif address==constants.TIMA: + elif address == constants.TIMA: self.set_timer_counter(data) - elif address==constants.TMA: + elif address == constants.TMA: self.set_timer_modulo(data) - elif address==constants.TAC: + elif address == constants.TAC: self.set_timer_control(data) def read(self, address): - if address==constants.DIV: + address = int(address) + if address == constants.DIV: return self.get_divider() - elif address==constants.TIMA: + elif address == constants.TIMA: return self.get_timer_counter() - elif address==constants.TMA: + elif address == constants.TMA: return self.get_timer_modulo() - elif address==constants.TAC: + elif address == constants.TAC: return self.get_timer_control() return 0xFF @@ -67,7 +72,7 @@ return 0xF8 | self.tac def set_timer_control(self, data): - if ((self.tac & 0x03) != (data & 0x03)): + if (self.tac & 0x03) != (data & 0x03): self.timer_clock = self.timer_cycles = constants.TIMER_CLOCK[data & 0x03] self.tac = data @@ -77,10 +82,12 @@ return self.divider_cycles def emulate(self, ticks): + ticks = int(ticks) self.emulate_divider(ticks) self.emulate_timer(ticks) def emulate_divider(self, ticks): + ticks = int(ticks) self.divider_cycles -= ticks if self.divider_cycles > 0: return @@ -89,6 +96,7 @@ self.divider_cycles += constants.DIV_CLOCK*count def emulate_timer(self, ticks): + ticks = int(ticks) if (self.tac & 0x04) == 0: return self.timer_cycles -= ticks Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/video.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/video.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/video.py Sat May 17 23:53:18 2008 @@ -29,35 +29,37 @@ self.frame_skip = frame_skip def reset(self): - self.cycles = constants.MODE_2_TICKS - self.control = 0x91 - self.stat = 2 - self.line_y = 0 + self.cycles = constants.MODE_2_TICKS + self.control = 0x91 + self.stat = 2 + self.line_y = 0 self.line_y_compare = 0 - self.dma = 0xFF - self.scroll_y = 0 - self.scroll_x = 0 - self.window_y = self.wline_y = 0 - self.window_x = 0 + self.dma = 0xFF + self.scroll_y = 0 + self.scroll_x = 0 + self.window_y = self.wline_y = 0 + self.window_x = 0 self.background_palette = 0xFC - self.object_palette_0 = self.object_palette_1 = 0xFF + self.object_palette_0 = 0xFF + self.object_palette_1 = 0xFF - self.transfer = True - self.display = True - self.vblank = True - self.dirty = True - - self.vram = [0]*constants.VRAM_SIZE - self.oam = [0]*constants.OAM_SIZE - - self.line = [0]* (8+160+8) - self.objects = [0] * constants.OBJECTS_PER_LINE - self.palette = [0] * 1024 + self.transfer = True + self.display = True + self.vblank = True + self.dirty = True + + self.vram = [0]*constants.VRAM_SIZE + self.oam = [0]*constants.OAM_SIZE + + self.line = [0]* (8+160+8) + self.objects = [0] * constants.OBJECTS_PER_LINE + self.palette = [0] * 1024 - self.frames = 0 + self.frames = 0 self.frame_skip = 0 def write(self, address, data): + address = int(address) # assert data >= 0x00 and data <= 0xFF if address == constants.LCDC : self.set_control(data) @@ -96,6 +98,7 @@ self.vram[address - constants.VRAM_ADDR] = data & 0xFF def read(self, address): + address = int(address) if address == constants.LCDC: return self.get_control() elif address == constants.STAT: @@ -136,6 +139,7 @@ return self.cycles def emulate(self, ticks): + ticks = int(ticks) if (self.control & 0x80) != 0: self.cycles -= ticks self.consume_cycles() @@ -307,7 +311,7 @@ def emulate_hblank_part_2(self): if self.display: - self.drawFrame() + self.draw_frame() self.frames += 1 if self.frames >= self.frame_skip: self.display = True From tverwaes at codespeak.net Sun May 18 00:05:13 2008 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Sun, 18 May 2008 00:05:13 +0200 (CEST) Subject: [pypy-svn] r54877 - pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk Message-ID: <20080517220513.B97342A8002@codespeak.net> Author: tverwaes Date: Sun May 18 00:05:12 2008 New Revision: 54877 Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/primitives.py Log: - removing all "as_x_get_shadow" for elements which will be come wrappers - disabled the primitive using as_x_get_shadow Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py Sun May 18 00:05:12 2008 @@ -278,26 +278,6 @@ from pypy.lang.smalltalk.shadow import ClassShadow return self.as_special_get_shadow(ClassShadow) - def as_link_get_shadow(self): - from pypy.lang.smalltalk.shadow import LinkShadow - return self.as_special_get_shadow(LinkShadow) - - def as_semaphore_get_shadow(self): - from pypy.lang.smalltalk.shadow import SemaphoreShadow - return self.as_special_get_shadow(SemaphoreShadow) - - def as_linkedlist_get_shadow(self): - from pypy.lang.smalltalk.shadow import LinkedListShadow - return self.as_special_get_shadow(LinkedListShadow) - - def as_process_get_shadow(self): - from pypy.lang.smalltalk.shadow import ProcessShadow - return self.as_special_get_shadow(ProcessShadow) - - def as_scheduler_get_shadow(self): - from pypy.lang.smalltalk.shadow import SchedulerShadow - return self.as_special_get_shadow(SchedulerShadow) - def as_blockcontext_get_shadow(self, invalid=True): from pypy.lang.smalltalk.shadow import BlockContextShadow return self.as_special_get_shadow(BlockContextShadow, invalid) Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/primitives.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/primitives.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/primitives.py Sun May 18 00:05:12 2008 @@ -728,10 +728,10 @@ @expose_primitive(PRIMITIVE_SIGNAL, unwrap_spec=[object]) def func(interp, w_rcvr): #if w_rcvr.getclass() != classtable.classtable['w_Semaphore']: - # raise PrimitiveFailedError() - assert isinstance(w_rcvr, model.W_PointersObject) - w_rcvr.as_semaphore_get_shadow().synchronous_signal(interp) - return w_rcvr + raise PrimitiveFailedError() + #assert isinstance(w_rcvr, model.W_PointersObject) + #w_rcvr.as_semaphore_get_shadow().synchronous_signal(interp) + #return w_rcvr @expose_primitive(PRIMITIVE_WAIT, unwrap_spec=[object]) def func(interp, w_rcvr): From cami at codespeak.net Sun May 18 10:49:13 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Sun, 18 May 2008 10:49:13 +0200 (CEST) Subject: [pypy-svn] r54878 - in pypy/branch/gameboy-emulator/pypy/lang/gameboy: . test Message-ID: <20080518084913.51B192A017B@codespeak.net> Author: cami Date: Sun May 18 10:49:11 2008 New Revision: 54878 Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboy.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/ram.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_ram.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/video.py Log: adapted ram test, so they can handle Exception fixed some wrong function signatures added BogusSound so we can do strange sounds Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py Sun May 18 10:49:11 2008 @@ -282,7 +282,7 @@ return self.rom[self.rom_bank + (address & 0x3FFF)] & 0xFF elif address >= 0xA000 and address <= 0xBFFF and self.ram_enable: # A000-BFFF return self.ram[self.ram_bank + (address & 0x1FFF)] & 0xFF - raise Exception("Invalid address") + raise Exception("MBC: Invalid address, out of range") def write(self, address, data): pass Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboy.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboy.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboy.py Sun May 18 10:49:11 2008 @@ -38,8 +38,9 @@ self.timer = Timer(self.interrupt) self.joypad = Joypad(self.joypad_driver, self.interrupt) self.video = Video(self.video_driver, self.interrupt, self) - self.sound = Sound(self.sound_driver) - + #self.sound = Sound(self.sound_driver) + self.sound = BogusSound() + def get_cartridge_manager(self): return self.cartridge_manager Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/ram.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/ram.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/ram.py Sun May 18 10:49:11 2008 @@ -18,19 +18,20 @@ def __init__(self): # Work RAM - self.w_ram = [0x00]*8192 + self.w_ram = [0]*8192 # High RAM - self.h_ram = [0x00]*128 + self.h_ram = [0]*128 self.reset() def reset(self): # Work RAM - self.w_ram = [0x00]*8192 + self.w_ram = [0]*8192 # High RAM - self.h_ram = [0x00]*128 + self.h_ram = [0]*128 def write(self, address, data): address = int(address) + data = int(data) if address >= 0xC000 and address <= 0xFDFF: # C000-DFFF Work RAM (8KB) # E000-FDFF Echo RAM @@ -48,4 +49,4 @@ elif address >= 0xFF80 and address <= 0xFFFE: # FF80-FFFE High RAM return self.h_ram[address & 0x7F] & 0xFF - return 0xFF + raise Exception("Invalid Memory access, address out of range") \ No newline at end of file Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/sound.py Sun May 18 10:49:11 2008 @@ -14,21 +14,23 @@ audio_frequency = 0 def __init__(self, sample_rate, frequency_table): - self.sample_rate = sample_rate + self.sample_rate = int(sample_rate) self.frequency_table = frequency_table - self.audio_length = 0 - self.audio_envelope = 0 + self.audio_length = 0 + self.audio_envelope = 0 self.audio_frequency = 0 - self.audio_playback = 0 - self.nr0 = 0 - self.nr1 = 0 - self.nr2 = 0 - self.nr3 = 0 - self.nr4 = 0 - self.audio_index = 0 - self.audio_length = 0 + self.audio_playback = 0 + self.nr0 = 0 + self.nr1 = 0 + self.nr2 = 0 + self.nr4 = 0 + self.nr3 = 0 + self.audio_index = 0 + self.audio_length = 0 self.audio_frequency = 0 - self.enabled = False + self.enabled = False + #XXX need to push this up into the Sound class + self.output_enable = False def reset(self): self.audio_index = 0 @@ -54,25 +56,25 @@ # Audio Channel 1 int def __init__(self, sample_rate, frequency_table): Channel.__init__(self, sample_rate, frequency_table) - self.sample_sweep = 0 - self.audio_1_index = 0 - self.audio_1_length = 0 - self.audio_volume = 0 + self.sample_sweep = 0 + self.audio_1_index = 0 + self.audio_1_length = 0 + self.audio_volume = 0 self.audio_1_envelope_length = 0 - self.sample_sweep_length = 0 - self.audio_1_frequency = 0 + self.sample_sweep_length = 0 + self.audio_1_frequency = 0 # Audio Channel 1 def get_audio_sweep(self): return self.sample_sweep def set_audio_sweep(self, data): - self.sample_sweep = data + self.sample_sweep = data self.sample_sweep_length = (constants.SOUND_CLOCK / 128) * \ ((self.sample_sweep >> 4) & 0x07) def set_audio_length(self, data): - self.audio_length = data + self.audio_length = data self.audio_1_length = (constants.SOUND_CLOCK / 256) * \ (64 - (self.audio_length & 0x3F)) @@ -109,55 +111,67 @@ (self.audio_envelope & 0x07) def update_audio(self): + self.update_enable() + self.update_volume_and_envelope() + self.update_frequency_and_playback() + + def update_enable(self): if (self.audio_playback & 0x40) != 0 and self.audio_1_length > 0: self.audio_1_length-=1 if self.audio_1_length <= 0: self.enabled = False - if self.audio_1_envelope_length > 0: - self.audio_1_envelope_length-=1 - if self.audio_1_envelope_length <= 0: - if (self.audio_envelope & 0x08) != 0: - if (self.audio_volume < 15): - self.audio_volume+=1 - elif self.audio_volume > 0: - self.audio_volume-=1 - self.audio_1_envelope_length += (constants.SOUND_CLOCK / 64) * \ - (self.audio_envelope & 0x07) + + def update_volume_and_envelope(self): + if self.audio_1_envelope_length <= 0: + return + self.audio_1_envelope_length -= 1 + if self.audio_1_envelope_length <= 0: + if (self.audio_envelope & 0x08) != 0: + if (self.audio_volume < 15): + self.audio_volume += 1 + elif self.audio_volume > 0: + self.audio_volume -= 1 + self.audio_1_envelope_length += (constants.SOUND_CLOCK / 64) * \ + (self.audio_envelope & 0x07) + + def update_frequency_and_playback(self): + if self.sample_sweep_length <= 0: + return + self.sample_sweep_length-=1 if self.sample_sweep_length > 0: - self.sample_sweep_length-=1 - if self.sample_sweep_length <= 0: - sweep_steps = (self.sample_sweep & 0x07) - if sweep_steps != 0: - frequency = ((self.audio_playback & 0x07) << 8) + \ - self.audio_frequency - if (self.sample_sweep & 0x08) != 0: - frequency -= frequency >> sweep_steps - else: - frequency += frequency >> sweep_steps - if frequency < 2048: - self.audio_1_frequency = self.frequency_table[frequency] - self.audio_frequency = frequency & 0xFF - self.audio_playback = (self.audio_playback & 0xF8) + \ - ((frequency >> 8) & 0x07) - else: - self.audio_1_frequency = 0 - self.output_enable &= ~0x01 - self.sample_sweep_length += (constants.SOUND_CLOCK / 128) * \ - ((self.sample_sweep >> 4) & 0x07) - - def mix_audio(self, buffer, length): + return + sweep_steps = (self.sample_sweep & 0x07) + if sweep_steps != 0: + frequency = ((self.audio_playback & 0x07) << 8) + \ + self.audio_frequency + if (self.sample_sweep & 0x08) != 0: + frequency -= frequency >> sweep_steps + else: + frequency += frequency >> sweep_steps + if frequency < 2048: + self.audio_1_frequency = self.frequency_table[frequency] + self.audio_frequency = frequency & 0xFF + self.audio_playback = (self.audio_playback & 0xF8) + \ + ((frequency >> 8) & 0x07) + else: + self.audio_1_frequency = 0 + self.output_enable &= ~0x01 + self.sample_sweep_length += (constants.SOUND_CLOCK / 128) * \ + ((self.sample_sweep >> 4) & 0x07) + + def mix_audio(self, buffer, length, output_terminal): wave_pattern = self.get_current_wave_pattern() for index in range(0, length, 3): self.audio_1_index += self.audio_1_frequency if (self.audio_1_index & (0x1F << 22)) >= wave_pattern: - if (self.output_terminal & 0x10) != 0: + if (output_terminal & 0x10) != 0: buffer[index + 0] -= self.audio_volume - if (self.output_terminal & 0x01) != 0: + if (output_terminal & 0x01) != 0: buffer[index + 1] -= self.audio_volume else: - if (self.output_terminal & 0x10) != 0: + if (output_terminal & 0x10) != 0: buffer[index + 0] += self.audio_volume - if (self.output_terminal & 0x01) != 0: + if (output_terminal & 0x01) != 0: buffer[index + 1] += self.audio_volume def get_current_wave_pattern(self): @@ -178,12 +192,11 @@ def __init__(self, sample_rate, frequency_table): Channel.__init__(self, sample_rate, frequency_table) - assert isinstance(sample_rate, int) - self.audio_2_index = 0 - self.audio_2_length = 0 - self.audio_volume = 0 + self.audio_2_index = 0 + self.audio_2_length = 0 + self.audio_volume = 0 self.audio_2_envelope_length = 0 - self.audio_2_frequency = 0 + self.audio_2_frequency = 0 # Audio Channel 2 def set_audio_length(self, data): @@ -203,14 +216,14 @@ self.audio_volume = (self.audio_volume + 2) & 0x0F def set_audio_frequency(self, data): - self.audio_frequency = data + self.audio_frequency = data self.audio_2_frequency = self.frequency_table[self.audio_frequency\ - + ((self.audio_playback & 0x07) << 8)] + + ((self.audio_playback & 0x07) << 8)] def set_audio_playback(self, data): - self.audio_playback = data + self.audio_playback = data self.audio_2_frequency = self.frequency_table[self.audio_frequency\ - + ((self.audio_playback & 0x07) << 8)] + + ((self.audio_playback & 0x07) << 8)] if (self.audio_playback & 0x80) != 0: self.enabled = True if (self.audio_playback & 0x40) != 0 and self.audio_2_length == 0: @@ -221,34 +234,42 @@ (self.audio_envelope & 0x07) def update_audio(self): + self.update_enable() + self.update_volume_and_envelope() + + def update_enable(self): if (self.audio_playback & 0x40) != 0 and self.audio_2_length > 0: self.audio_2_length-=1 if self.audio_2_length <= 0: self.enabled = False + + def update_volume_and_envelope(self): + if self.audio_2_envelope_length <= 0: + return + self.audio_2_envelope_length-=1 if self.audio_2_envelope_length > 0: - self.audio_2_envelope_length-=1 - if self.audio_2_envelope_length <= 0: - if (self.audio_envelope & 0x08) != 0: - if self.audio_volume < 15: - self.audio_volume+=1 - elif self.audio_volume > 0: - self.audio_volume-=1 - self.audio_2_envelope_length += (constants.SOUND_CLOCK / 64) *\ - (self.audio_envelope & 0x07) + return + if (self.audio_envelope & 0x08) != 0: + if self.audio_volume < 15: + self.audio_volume+=1 + elif self.audio_volume > 0: + self.audio_volume-=1 + self.audio_2_envelope_length += (constants.SOUND_CLOCK / 64) *\ + (self.audio_envelope & 0x07) - def mix_audio(self, buffer, length): + def mix_audio(self, buffer, length, output_terminal): wave_pattern = self.get_current_wave_pattern() for index in range(0, length): self.audio_2_index += self.audio_2_frequency - if ((self.audio_2_index & (0x1F << 22)) >= wave_pattern): - if ((self.output_terminal & 0x20) != 0): + if (self.audio_2_index & (0x1F << 22)) >= wave_pattern: + if (output_terminal & 0x20) != 0: buffer[index + 0] -= self.audio_volume - if ((self.output_terminal & 0x02) != 0): + if (output_terminal & 0x02) != 0: buffer[index + 1] -= self.audio_volume else: - if ((self.output_terminal & 0x20) != 0): + if (output_terminal & 0x20) != 0: buffer[index + 0] += self.audio_volume - if ((self.output_terminal & 0x02) != 0): + if (output_terminal & 0x02) != 0: buffer[index + 1] += self.audio_volume def get_current_wave_pattern(self): @@ -268,11 +289,11 @@ def __init__(self, sample_rate, frequency_table): Channel.__init__(self, sample_rate, frequency_table) - self.audio_enable = 0 - self.audio_level = 0 - self.audio_3_index = 0 - self.audio_3_length = 0 - self.audio_3_frequency = 0 + self.audio_enable = 0 + self.audio_level = 0 + self.audio_3_index = 0 + self.audio_3_length = 0 + self.audio_3_frequency = 0 self.audio_wave_pattern = [0]*16 def get_audio_enable(self): @@ -325,7 +346,7 @@ if self.audio_3_length <= 0: self.output_enable &= ~0x04 - def mix_audio(self, buffer, length): + def mix_audio(self, buffer, length, output_terminal): wave_pattern = self.get_current_wave_pattern() for index in range(0, length, 2): self.audio_3_index += self.audio_3_frequency @@ -335,9 +356,9 @@ else: sample = (sample >> 4) & 0x0F sample = int(((sample - 8) << 1) >> self.audio_level) - if (self.output_terminal & 0x40) != 0: + if (output_terminal & 0x40) != 0: buffer[index + 0] += sample - if (self.output_terminal & 0x04) != 0: + if (output_terminal & 0x04) != 0: buffer[index + 1] += sample def get_current_wave_pattern(self): @@ -356,14 +377,13 @@ def __init__(self, sample_rate, frequency_table): Channel.__init__(self, sample_rate, frequency_table) # Audio Channel 4 int - self.audio_length = 0 - self.audio_polynomial = 0 - self.audio_4_index = 0 - self.audio_4_length = 0 - self.audio_volume = 0 + self.audio_length = 0 + self.audio_polynomial = 0 + self.audio_4_index = 0 + self.audio_4_length = 0 + self.audio_volume = 0 self.audio_4_envelope_length = 0 - self.audio_4_frequency = 0 - + self.audio_4_frequency = 0 self.generate_noise_frequency_ratio_table() self.generate_noise_tables() @@ -427,14 +447,15 @@ def set_audio_envelope(self, data): self.audio_envelope = data - if (self.audio_playback & 0x40) == 0: - if (self.audio_envelope >> 4) == 0: - self.audio_volume = 0 - elif self.audio_4_envelope_length == 0 and \ - (self.audio_envelope & 0x07) == 0: - self.audio_volume = (self.audio_volume + 1) & 0x0F - else: - self.audio_volume = (self.audio_volume + 2) & 0x0F + if (self.audio_playback & 0x40) is not 0: + return + if (self.audio_envelope >> 4) == 0: + self.audio_volume = 0 + elif self.audio_4_envelope_length == 0 and \ + (self.audio_envelope & 0x07) == 0: + self.audio_volume = (self.audio_volume + 1) & 0x0F + else: + self.audio_volume = (self.audio_volume + 2) & 0x0F def set_audio_polynomial(self, data): self.audio_polynomial = data @@ -446,33 +467,42 @@ def set_audio_playback(self, data): self.audio_playback = data - if (self.audio_playback & 0x80) != 0: - self.enabled = True - if (self.audio_playback & 0x40) != 0 and self.audio_4_length == 0: - self.audio_4_length = (constants.SOUND_CLOCK / 256) * \ - (64 - (self.audio_length & 0x3F)) - self.audio_volume = self.audio_envelope >> 4 - self.audio_4_envelope_length = (constants.SOUND_CLOCK / 64) * \ - (self.audio_envelope & 0x07) - self.audio_4_index = 0 + if (self.audio_playback & 0x80) == 0: + return + self.enabled = True + if (self.audio_playback & 0x40) != 0 and self.audio_4_length == 0: + self.audio_4_length = (constants.SOUND_CLOCK / 256) * \ + (64 - (self.audio_length & 0x3F)) + self.audio_volume = self.audio_envelope >> 4 + self.audio_4_envelope_length = (constants.SOUND_CLOCK / 64) * \ + (self.audio_envelope & 0x07) + self.audio_4_index = 0 def update_audio(self): + self.update_enabled() + self.update_envelope_and_volume() + + def update_enabled(self): if (self.audio_playback & 0x40) != 0 and self.audio_4_length > 0: self.audio_4_length-=1 if self.audio_4_length <= 0: self.output_enable &= ~0x08 + + def update_envelope_and_volume(self): + if self.audio_4_envelope_length <= 0: + return + self.audio_4_envelope_length-=1 if self.audio_4_envelope_length > 0: - self.audio_4_envelope_length-=1 - if self.audio_4_envelope_length <= 0: - if (self.audio_envelope & 0x08) != 0: - if self.audio_volume < 15: - self.audio_volume+=1 - elif self.audio_volume > 0: - self.audio_volume-=1 - self.audio_4_envelope_length += (constants.SOUND_CLOCK / 64) *\ - (self.audio_envelope & 0x07) - - def mix_audio(self, buffer, length): + return + if (self.audio_envelope & 0x08) != 0: + if self.audio_volume < 15: + self.audio_volume+=1 + elif self.audio_volume > 0: + self.audio_volume-=1 + self.audio_4_envelope_length += (constants.SOUND_CLOCK / 64) *\ + (self.audio_envelope & 0x07) + + def mix_audio(self, buffer, length, output_terminal): for index in range(0, length, 2): self.audio_4_index += self.audio_4_frequency #polynomial @@ -487,14 +517,14 @@ polynomial = self.noise_step_15_table[self.audio_4_index >> 21] >> \ ((self.audio_4_index >> 16) & 31) if (polynomial & 1) != 0: - if (self.output_terminal & 0x80) != 0: + if (output_terminal & 0x80) != 0: buffer[index + 0] -= self.audio_volume - if (self.output_terminal & 0x08) != 0: + if (output_terminal & 0x08) != 0: buffer[index + 1] -= self.audio_volume else: - if (self.output_terminal & 0x80) != 0: + if (output_terminal & 0x80) != 0: buffer[index + 0] += self.audio_volume - if (self.output_terminal & 0x08) != 0: + if (output_terminal & 0x08) != 0: buffer[index + 1] += self.audio_volume @@ -505,13 +535,13 @@ class Sound(iMemory): def __init__(self, sound_driver): - self.buffer = [0] * 512 - self.outputLevel = 0 + self.buffer = [0] * 512 + self.outputLevel = 0 self.output_terminal = 0 - self.output_enable = 0 + self.output_enable = 0 - self.driver = sound_driver - self.sample_rate = self.driver.get_sample_rate() + self.driver = sound_driver + self.sample_rate = self.driver.get_sample_rate() self.generate_frequency_table() self.create_audio_channels() @@ -591,7 +621,7 @@ return self.cycles def emulate(self, ticks): - ticks = int(ticks) + ticks = int(ticks) self.cycles -= ticks while (self.cycles <= 0): self.update_audio() @@ -601,7 +631,7 @@ def mix_down_audio(self): self.frames += self.driver.get_sample_rate() - length = (self.frames / constants.SOUND_CLOCK) << 1 + length = (self.frames / constants.SOUND_CLOCK) << 1 self.mix_audio(self.buffer, length) self.driver.write(self.buffer, length) self.frames %= constants.SOUND_CLOCK @@ -729,13 +759,13 @@ if (self.output_enable & 0x80) == 0: return if (self.output_enable & 0x01) != 0: - self.channel1.mix_audio(buffer, length) + self.channel1.mix_audio(buffer, length, self.output_terminal) if (self.output_enable & 0x02) != 0: - self.channel2.mix_audio(buffer, length) + self.channel2.mix_audio(buffer, length, self.output_terminal) if (self.output_enable & 0x04) != 0: - self.channel3.mix_audio(buffer, length) + self.channel3.mix_audio(buffer, length, self.output_terminal) if (self.output_enable & 0x08) != 0: - self.channel4.mix_audio(buffer, length) + self.channel4.mix_audio(buffer, length, self.output_terminal) # Output Control def get_output_level(self): @@ -759,6 +789,26 @@ self.output_enable &= 0xF0 +class BogusSound(iMemory): + """ + Used for development purposes + """ + def __init__(self): + pass + + def get_cycles(self): + return + + def reset(self): + pass + + def get_cycles(self): + return 0xFF + + def emulate(self, ticks): + pass + + # SOUND DRIVER ----------------------------------------------------------------- Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_ram.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_ram.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_ram.py Sun May 18 10:49:11 2008 @@ -11,7 +11,12 @@ address = 0x00 value = 0x12 ram.write(address, value) - assert ram.read(address) == 0xFF + try: + ram.read(address) + py.test.fail() + except Exception: + pass + assert value not in ram.w_ram assert value not in ram.h_ram @@ -46,6 +51,10 @@ address += 1 value += 1 ram.write(address, value) - assert ram.read(address) == 0xFF + try: + ram.read(address) + py.test.fail() + except Exception: + pass assert value not in ram.h_ram assert value not in ram.w_ram \ No newline at end of file Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/video.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/video.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/video.py Sun May 18 10:49:11 2008 @@ -492,19 +492,19 @@ x += 8 def get_pattern(self, address): - pattern = self.vram[address] & 0xFF + pattern = self.vram[address] & 0xFF pattern += (self.vram[address + 1] & 0xFF) << 8 return pattern - def draw_object(self, setter): + def draw_object(self, setter, x, address, flags): pattern = self.get_pattern(address) - self.mask = 0 + mask = 0 # priority if (flags & 0x80) != 0: - self.mask |= 0x0008 + mask |= 0x0008 # palette if (flags & 0x10) != 0: - self.mask |= 0x0004 + mask |= 0x0004 if (flags & 0x20) != 0: self.draw_object_normal(x, pattern, mask, setter) else: @@ -514,19 +514,19 @@ for i in range(0, 7): color = pattern >> (6-i) if (color & 0x0202) != 0: - setter(self, x+1, color, mask) + setter(x+1, color, mask) color = pattern << 1 if (color & 0x0202) != 0: - setter(self, x+7, color, mask) + setter(x+7, color, mask) def draw_object_flipped(self, x, pattern, mask, setter): color = pattern << 1 if (color & 0x0202) != 0: - setter(self, x, color | mask) + setter(x, color, mask) for i in range(0, 7): color = pattern >> i if (color & 0x0202) != 0: - setter(self, x + i + 1, color | mask) + setter(x + i + 1, color, mask) def draw_tile(self, x, address): pattern = self.get_pattern(address) @@ -534,14 +534,13 @@ self.line[x + i] = (pattern >> (7-i)) & 0x0101 def draw_object_tile(self, x, address, flags): - pattern = self.get_pattern(address) - self.draw_object(self.setTileLine) + self.draw_object(self.set_tile_line, x, address, flags) def set_tile_line(self, pos, color, mask): self.line[pos] |= color | mask def draw_overlapped_object_tile(self, x, address, flags): - self.draw_object(self.setOverlappedObjectLine) + self.draw_object(self.setOverlappedObjectLine, x, address, flags) def set_overlapped_object_line(self, pos, color, mask): self.line[pos] = (self.line[pos] & 0x0101) | color | mask From antocuni at codespeak.net Sun May 18 10:53:47 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Sun, 18 May 2008 10:53:47 +0200 (CEST) Subject: [pypy-svn] r54879 - in pypy/branch/oo-jit/pypy: annotation jit/codegen/cli jit/codegen/test Message-ID: <20080518085347.863D02A0180@codespeak.net> Author: antocuni Date: Sun May 18 10:53:47 2008 New Revision: 54879 Modified: pypy/branch/oo-jit/pypy/annotation/builtin.py pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py pypy/branch/oo-jit/pypy/jit/codegen/test/rgenop_tests.py Log: fix the annotation of cast_from_object; simplify the various revealconst(). More steps toward making test_gencli_portal.test_very_simple passing. Modified: pypy/branch/oo-jit/pypy/annotation/builtin.py ============================================================================== --- pypy/branch/oo-jit/pypy/annotation/builtin.py (original) +++ pypy/branch/oo-jit/pypy/annotation/builtin.py Sun May 18 10:53:47 2008 @@ -575,7 +575,7 @@ def cast_from_object(T, obj): TYPE = T.const if TYPE is ootype.Object: - return T + return SomeOOObject() elif isinstance(TYPE, ootype.Instance): return SomeOOInstance(TYPE) elif isinstance(TYPE, ootype.Record): Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py (original) +++ pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py Sun May 18 10:53:47 2008 @@ -1,6 +1,7 @@ from pypy.tool.pairtype import extendabletype from pypy.rlib.rarithmetic import intmask from pypy.rpython.ootypesystem import ootype +from pypy.rpython.lltypesystem import lltype from pypy.rlib.objectmodel import specialize from pypy.jit.codegen.model import AbstractRGenOp, GenBuilder, GenLabel from pypy.jit.codegen.model import GenVarOrConst, GenVar, GenConst, CodeGenSwitch @@ -96,14 +97,9 @@ @specialize.arg(1) def revealconst(self, T): - if T is ootype.Signed: - return self.value - elif T is ootype.Bool: - return bool(self.value) - elif T is ootype.Char: - return chr(self.value) - else: - assert False + if T is ootype.Object: + return ootype.NULL # XXX? + return lltype.cast_primitive(T, self.value) def getCliType(self): return class2type(self.cliclass) @@ -122,8 +118,9 @@ @specialize.arg(1) def revealconst(self, T): - assert T is ootype.Float - return self.value + if T is ootype.Object: + return ootype.NULL # XXX? + return lltype.cast_primitive(T, self.value) def getCliType(self): return typeof(System.Double) @@ -161,7 +158,7 @@ def getCliType(self): if self.obj == ootype.NULL: - return cObject + return class2type(cObject) cliobj = dotnet.cast_to_native_object(self.obj) return cliobj.GetType() @@ -169,21 +166,22 @@ return self.obj def load(self, builder): - import pdb;pdb.set_trace() - index = self._get_index(builder) - if self.obj is None: - t = typeof(System.Object) - else: - t = self.obj.GetType() - self._load_from_array(builder, index, t) + assert False, 'XXX' +## import pdb;pdb.set_trace() +## index = self._get_index(builder) +## if self.obj is None: +## t = typeof(System.Object) +## else: +## t = self.obj.GetType() +## self._load_from_array(builder, index, t) @specialize.arg(1) def revealconst(self, T): - if T is ootype.Signed: - return ootype.ooidentityhash(self.obj) - elif T is ootype.Unsigned: - return intmask(ootype.ooidentityhash(self.obj)) - return ootype.cast_from_object(T, self.obj) + if isinstance(T, ootype.OOType): + return ootype.cast_from_object(T, self.obj) + else: + h = ootype.ooidentityhash(self.obj) + return lltype.cast_primitive(T, h) OBJECT = System.Object._INSTANCE Modified: pypy/branch/oo-jit/pypy/jit/codegen/test/rgenop_tests.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/codegen/test/rgenop_tests.py (original) +++ pypy/branch/oo-jit/pypy/jit/codegen/test/rgenop_tests.py Sun May 18 10:53:47 2008 @@ -2242,7 +2242,7 @@ if self.T.__name__ == 'LLType': assert gv.revealconst(llmemory.Address) == llmemory.NULL else: - assert gv.revealconst(ootype.ROOT) == ootype.null(ootype.ROOT) + assert gv.revealconst(ootype.Object) == ootype.null(ootype.Object) def test_ovfcheck_adder_direct(self): rgenop = self.RGenOp() From cfbolz at codespeak.net Sun May 18 10:59:09 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sun, 18 May 2008 10:59:09 +0200 (CEST) Subject: [pypy-svn] r54880 - pypy/extradoc/sprintinfo/berlin-2008 Message-ID: <20080518085909.9E9172A0181@codespeak.net> Author: cfbolz Date: Sun May 18 10:59:06 2008 New Revision: 54880 Modified: pypy/extradoc/sprintinfo/berlin-2008/planning.txt Log: (all): planning for today Modified: pypy/extradoc/sprintinfo/berlin-2008/planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/berlin-2008/planning.txt (original) +++ pypy/extradoc/sprintinfo/berlin-2008/planning.txt Sun May 18 10:59:06 2008 @@ -20,14 +20,21 @@ Tasks: - - gameboy emulator - - adding sdl bindings to rpython (Camillo, Karl, Armin) - - django porting - - making sqlite-ctypes work on PyPy (Samuele, Felix, Maciek) - - hybrid-io-improvements branch - - work on SPy, decide about the branch (Alexander, Toon, Carl Friedrich) - - complete Stackless interface (Adrian, Stephan, Peter) - - discussions/starting on separate compilation + - gameboy emulator: trying to translate, lots of blocked blocks (Armin looking, Camillo) + - adding sdl bindings to rpython (Camillo, Karl, Armin) IN-PROGRESS + - django porting: using django with sqlite-ctypes works (Samuele, Maciek) + 90/200 tests failing + more robustapply work + dictionary subclassing + - making sqlite-ctypes work on PyPy DONE (mostly) + - hybrid-io-improvements branch: discussions happened + - work on SPy, decide about the branch (Toon, Carl Friedrich) + work on sanitizing the spy shadow branch + - complete Stackless interface (Stephan, Peter) + work on channel preferences + some cleanup needed + - discussions/starting on separate compilation (Armin, Samuele, Maciek, Alexander) + - discuss our own GCs and threads - work on PyPy's JIT generator: we are refactoring parts of the From stephan at codespeak.net Sun May 18 11:36:50 2008 From: stephan at codespeak.net (stephan at codespeak.net) Date: Sun, 18 May 2008 11:36:50 +0200 (CEST) Subject: [pypy-svn] r54881 - in pypy/dist/pypy/lib: . app_test Message-ID: <20080518093650.2031F2A017B@codespeak.net> Author: stephan Date: Sun May 18 11:36:50 2008 New Revision: 54881 Modified: pypy/dist/pypy/lib/app_test/test_stackless.py pypy/dist/pypy/lib/stackless.py Log: stackless now has 'channel preference' implemented Modified: pypy/dist/pypy/lib/app_test/test_stackless.py ============================================================================== --- pypy/dist/pypy/lib/app_test/test_stackless.py (original) +++ pypy/dist/pypy/lib/app_test/test_stackless.py Sun May 18 11:36:50 2008 @@ -44,7 +44,21 @@ assert rlist == 'm g f m'.split() def test_with_channel(self): + pref = {} + pref[-1] = ['s0', 'r0', 's1', 'r1', 's2', 'r2', + 's3', 'r3', 's4', 'r4', 's5', 'r5', + 's6', 'r6', 's7', 'r7', 's8', 'r8', + 's9', 'r9'] + pref[0] = ['s0', 'r0', 's1', 's2', 'r1', 'r2', + 's3', 's4', 'r3', 'r4', 's5', 's6', + 'r5', 'r6', 's7', 's8', 'r7', 'r8', + 's9', 'r9'] + pref[1] = ['s0', 's1', 'r0', 's2', 'r1', 's3', + 'r2', 's4', 'r3', 's5', 'r4', 's6', + 'r5', 's7', 'r6', 's8', 'r7', 's9', + 'r8', 'r9'] rlist = [] + def f(outchan): for i in range(10): rlist.append('s%s' % i) @@ -58,17 +72,17 @@ break rlist.append('r%s' % val) - ch = stackless.channel() - t1 = stackless.tasklet(f)(ch) - t2 = stackless.tasklet(g)(ch) + for preference in [-1, 0, 1]: + rlist = [] + ch = stackless.channel() + ch.preference = preference + t1 = stackless.tasklet(f)(ch) + t2 = stackless.tasklet(g)(ch) - stackless.run() + stackless.run() - assert len(rlist) == 20 - for i in range(10): - (s,r), rlist = rlist[:2], rlist[2:] - assert s == 's%s' % i - assert r == 'r%s' % i + assert len(rlist) == 20 + assert rlist == pref[preference] def test_send_counter(self): import random Modified: pypy/dist/pypy/lib/stackless.py ============================================================================== --- pypy/dist/pypy/lib/stackless.py (original) +++ pypy/dist/pypy/lib/stackless.py Sun May 18 11:36:50 2008 @@ -4,6 +4,13 @@ Please refer to their documentation. """ +DEBUG = True + +def dprint(*args): + for arg in args: + print arg, + print + import traceback import sys try: @@ -209,6 +216,48 @@ is resumed. If there is no waiting receiver, the sender is suspended. By receiving from a channel, a tasklet that is waiting to send is resumed. If there is no waiting sender, the receiver is suspended. + + Attributes: + + preference + ---------- + -1: prefer receiver + 0: don't prefer anything + 1: prefer sender + + Pseudocode that shows in what situation a schedule happens: + + def send(arg): + if !receiver: + schedule() + elif schedule_all: + schedule() + else: + if (prefer receiver): + schedule() + else (don't prefer anything, prefer sender): + pass + + NOW THE INTERESTING STUFF HAPPENS + + def receive(): + if !sender: + schedule() + elif schedule_all: + schedule() + else: + if (prefer sender): + schedule() + else (don't prefer anything, prefer receiver): + pass + + NOW THE INTERESTING STUFF HAPPENS + + schedule_all + ------------ + True: overwrite preference. This means that the current tasklet always + schedules before returning from send/receive (it always blocks). + (see Stackless/module/channelobject.c) """ def __init__(self, label=''): @@ -216,6 +265,8 @@ self.closing = False self.queue = deque() self.label = label + self.preference = -1 + self.schedule_all = False def __str__(self): return 'channel[%s](%s,%s)' % (self.label, self.balance, self.queue) @@ -239,6 +290,63 @@ """ self.closing = False + def _channel_action(self, arg, d): + """ + d == -1 : receive + d == 1 : send + + the original CStackless has an argument 'stackl' which is not used + here. + + 'target' is the peer tasklet to the current one + """ + do_schedule=False + assert abs(d) == 1 + source = getcurrent() + source.tempval = arg + if d > 0: + cando = self.balance < 0 + dir = d + else: + cando = self.balance > 0 + dir = 0 + + if _channel_callback is not None: + _channel_callback(self, source, dir, not cando) + self.balance += d + if cando: + # communication 1): there is somebody waiting + target = self.queue.popleft() + source.tempval, target.tempval = target.tempval, source.tempval + target.blocked = 0 + if self.schedule_all: + # always schedule + _scheduler_append(target) + do_schedule = True + elif self.preference == -d: + _scheduler_append(target, False) + do_schedule = True + else: + _scheduler_append(target) + else: + # communication 2): there is nobody waiting +# if source.block_trap: +# raise RuntimeError("this tasklet does not like to be blocked") +# if self.closing: +# raise StopIteration() + source.blocked = d + self.queue.append(source) + _scheduler_remove(getcurrent()) + do_schedule = True + + if do_schedule: + schedule() + + retval = source.tempval + if isinstance(retval, bomb): + retval.raise_() + return retval + def receive(self): """ channel.receive() -- receive a value over the channel. @@ -247,32 +355,9 @@ continue immediately, and the sender is put at the end of the runnables list. The above policy can be changed by setting channel flags. - XXX channel flags are not implemented, yet. """ - receiver = getcurrent() - willblock = not self.balance > 0 - if _channel_callback is not None: - _channel_callback(self, receiver, 0, willblock) - if self.balance > 0: # somebody is already sending - self.balance -= 1 - sender = self.queue.popleft() - sender.blocked = False - receiver.tempval = sender.tempval - _scheduler_append(sender) - else: # nobody is waiting - self.balance -= 1 - self.queue.append(receiver) - receiver.blocked = True - _scheduler_remove(getcurrent()) - schedule() - assert not receiver.blocked - - # XXX wrong. This check should happen on every context switch, not here. - msg = receiver.tempval - if isinstance(msg, bomb): - msg.raise_() - return msg - + return self._channel_action(None, -1) + register_stackless_primitive(receive, retval_expr='receiver.tempval') def send_exception(self, exp_type, msg): @@ -290,25 +375,7 @@ be activated immediately, and the sender is put at the end of the runnables list. """ - sender = getcurrent() - sender.tempval = msg - willblock = not self.balance < 0 - if _channel_callback is not None: - _channel_callback(self, sender, 1, willblock) - if self.balance < 0: # somebody is already waiting - receiver = self.queue.popleft() - receiver.blocked = False - self.balance += 1 - receiver.tempval = msg - _scheduler_append(receiver, False) - schedule() - else: # nobody is waiting - self.queue.append(sender) - sender.blocked = True - self.balance += 1 - _scheduler_remove(getcurrent()) - schedule() - assert not sender.blocked + return self._channel_action(msg, 1) register_stackless_primitive(send) From tverwaes at codespeak.net Sun May 18 13:09:21 2008 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Sun, 18 May 2008 13:09:21 +0200 (CEST) Subject: [pypy-svn] r54882 - pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk Message-ID: <20080518110921.8F7381684EC@codespeak.net> Author: tverwaes Date: Sun May 18 13:09:19 2008 New Revision: 54882 Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/constants.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/wrapper.py Log: (tverwaes, cfbolz) moving scheduler to wrappers. Added first test for puttosleep; need more tests; hungry Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/constants.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/constants.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/constants.py Sun May 18 13:09:19 2008 @@ -15,10 +15,6 @@ CLASS_FORMAT_INDEX = 2 CLASS_NAME_INDEX = 6 # in the mini.image, at least -# Scheduler -SCHEDULER_PROCESS_LISTS_INDEX = 0 -SCHEDULER_ACTIVE_PROCESS_INDEX = 1 - # MethodDict METHODDICT_TALLY_INDEX = 0 METHODDICT_VALUES_INDEX = 1 Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/wrapper.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/wrapper.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/wrapper.py Sun May 18 13:09:19 2008 @@ -1,4 +1,5 @@ from pypy.lang.smalltalk import model +from pypy.lang.smalltalk import utility class Wrapper(object): def __init__(self, w_self): @@ -40,6 +41,33 @@ priority = make_getter(2) my_list, store_my_list = make_getter_setter(3) + def put_to_sleep(self): + sched = scheduler() + priority = self.priority() + process_list = sched.get_process_list(priority) + process_list.add_process(self.w_self) + + def activate(self, interp): + from pypy.lang.smalltalk import objtable + sched = scheduler() + w_old_process = sched.active_process() + sched.store_active_process(self.w_self) + ProcessWrapper(w_old_process).store_suspended_context(interp.w_active_context()) + interp.store_w_active_context(self.suspended_context()) + self.store_suspended_context(objtable.w_nil) + + def resume(self, interp): + sched = scheduler() + active_process = ProcessWrapper(sched.active_process()) + active_priority = active_process.priority() + priority = self.priority() + if priority > active_priority: + active_process.put_to_sleep() + self.activate(interp) + else: + self.put_to_sleep(process) + + class LinkedListWrapper(Wrapper): first_link, store_first_link = make_getter_setter(0) last_link, store_last_link = make_getter_setter(1) @@ -68,78 +96,37 @@ LinkWrapper(w_first).store_next_link(objtable.w_nil) return w_first +class ProcessListWrapper(LinkedListWrapper): + def add_process(self, w_process): + self.add_last_link(w_process) + ProcessWrapper(w_process).store_my_list(self.w_self) + class AssociationWrapper(Wrapper): key = make_getter(0) value, store_value = make_getter_setter(1) -''' -class SchedulerShadow(AbstractShadow): - def __init__(self, w_self, invalid): - AbstractShadow.__init__(self, w_self, invalid) - - def s_active_process(self): - w_v = self.w_self()._vars[constants.SCHEDULER_ACTIVE_PROCESS_INDEX] - assert isinstance(w_v, model.W_PointersObject) - return w_v.as_process_get_shadow() - - def store_w_active_process(self, w_object): - self.w_self()._vars[constants.SCHEDULER_ACTIVE_PROCESS_INDEX] = w_object +class SchedulerWrapper(Wrapper): + priority_list = make_getter(0) + active_process, store_active_process = make_getter_setter(1) - def process_lists(self): - w_v = self.w_self()._vars[constants.SCHEDULER_PROCESS_LISTS_INDEX] - assert isinstance(w_v, model.W_PointersObject) - return w_v - - + def get_process_list(self, w_priority): + priority = utility.unwrap_int(w_priority) + lists = self.priority_list() + return ProcessListWrapper(Wrapper(lists).read(priority)) + +def scheduler(): + from pypy.lang.smalltalk import objtable + w_association = objtable.objtable["w_schedulerassociationpointer"] + assert w_association is not None + w_scheduler = AssociationWrapper(w_association).value() + assert isinstance(w_scheduler, model.W_PointersObject) + return SchedulerWrapper(w_scheduler) class SemaphoreWrapper(LinkedListWrapper): excess_signals, store_excess_signals = make_getter_setter(0) - def __init__(self, w_self, invalid=False): - LinkedListShadow.__init__(self, w_self, invalid) - - def put_to_sleep(self, s_process): - priority = s_process.priority() - s_scheduler = self.s_scheduler() - w_process_lists = s_scheduler.process_lists() - w_process_list = w_process_lists._vars[priority] - assert isinstance(w_process_list, model.W_PointersObject) - w_process_list.as_linkedlist_get_shadow().add_last_link(s_process.w_self()) - s_process.store_my_list(w_process_list) - - def transfer_to(self, s_process, interp): - from pypy.lang.smalltalk import objtable - s_scheduler = self.s_scheduler() - s_old_process = s_scheduler.s_active_process() - s_scheduler.store_w_active_process(s_process.w_self()) - s_old_process.store_w_suspended_context(interp.s_active_context().w_self()) - interp.store_w_active_context(s_process.w_suspended_context()) - s_process.store_w_suspended_context(objtable.w_nil) - #reclaimableContextCount := 0 - - def s_scheduler(self): - from pypy.lang.smalltalk import objtable - w_association = objtable.objtable["w_schedulerassociationpointer"] - assert w_association is not None - assert isinstance(w_association, model.W_PointersObject) - w_scheduler = w_association.as_association_get_shadow().value() - assert isinstance(w_scheduler, model.W_PointersObject) - return w_scheduler.as_scheduler_get_shadow() - - def resume(self, w_process, interp): - process = ProcessWrapper(w_process) - scheduler = self.scheduler() - active_process = scheduler.s_active_process() - active_priority = active_process.priority() - new_priority = process.priority() - if new_priority > active_priority: - self.put_to_sleep(active_process) - self.transfer_to(process, interp) - else: - self.put_to_sleep(process) - - def synchronous_signal(self, interp): + def signal(self, interp): if self.is_empty_list(): w_value = self.excess_signals() w_value = utility.wrap_int(utility.unwrap_int(w_value) + 1) @@ -147,5 +134,11 @@ else: self.resume(self.remove_first_link_of_list(), interp) -''' - + def wait(self, w_process, interp): + excess = utility.unwrap_int(self.excess_signals()) + if excess > 0: + w_excess = utility.wrap_int(excess - 1) + self.store_excess_signals(w_excess) + else: + self.add_last_link(w_process) + ProcessWrapper(w_process).put_to_sleep() From cami at codespeak.net Sun May 18 14:38:05 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Sun, 18 May 2008 14:38:05 +0200 (CEST) Subject: [pypy-svn] r54883 - in pypy/branch/gameboy-emulator/pypy/lang/gameboy: . test Message-ID: <20080518123805.02E81168529@codespeak.net> Author: cami Date: Sun May 18 14:38:03 2008 New Revision: 54883 Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboy.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboyImplementation.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/interrupt.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/joypad.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cpu.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_register.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/timer.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/video.py Log: added more CallWrappers, ranlsation still fails Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py Sun May 18 14:38:03 2008 @@ -128,7 +128,7 @@ + (self.rom[constants.CHECKSUM_B_ADDRESS] & 0xFF) def has_battery(self): - return has_cartridge_battery(self.getMemoryBankType()) + return has_cartridge_battery(self.get_memory_bank_type()) def verify(self): checksum = 0 @@ -323,7 +323,7 @@ def reset(self): MBC.reset(self) - self.memoryModel = 0 + self.memory_model = 0 def write(self, address, data): if address <= 0x1FFF: # 0000-1FFF @@ -333,7 +333,7 @@ elif address <= 0x5FFF: # 4000-5FFF self.write_rom_bank_2(address, data) elif address <= 0x7FFF: # 6000-7FFF - self.memoryModel = data & 0x01 + self.memory_model = data & 0x01 elif address >= 0xA000 and address <= 0xBFFF and self.ram_enable: # A000-BFFF self.ram[self.ram_bank + (address & 0x1FFF)] = data @@ -344,13 +344,13 @@ def write_rom_bank_1(self, address, data): if (data & 0x1F) == 0: data = 1 - if self.memoryModel == 0: + if self.memory_model == 0: self.rom_bank = ((self.rom_bank & 0x180000) + ((data & 0x1F) << 14)) & self.rom_size else: self.rom_bank = ((data & 0x1F) << 14) & self.rom_size def write_rom_bank_2(self, address, data): - if self.memoryModel == 0: + if self.memory_model == 0: self.rom_bank = ((self.rom_bank & 0x07FFFF) + ((data & 0x03) << 19)) & self.rom_size else: self.ram_bank = ((data & 0x03) << 13) & self.ram_size Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py Sun May 18 14:38:03 2008 @@ -47,15 +47,15 @@ self.lo = lo self.reset_value = reset_value - def set(self, hi=0, lo=-1, use_cycles=True): - if lo < 0: - self.set_hi(hi >> 8, use_cycles) - self.set_lo(hi & 0xFF, use_cycles) - if use_cycles: - self.cpu.cycles += 1 - else: - self.set_hi(hi, use_cycles) - self.set_lo(lo, use_cycles) + def set(self, value, use_cycles=True): + self.set_hi(value >> 8, use_cycles) + self.set_lo(value & 0xFF, use_cycles) + if use_cycles: + self.cpu.cycles += 1 + + def set_hi_lo(self, hi, lo, use_cycles=True): + self.set_hi(hi, use_cycles) + self.set_lo(lo, use_cycles) def reset(self): self.set(self.reset_value, use_cycles=False) @@ -125,7 +125,10 @@ self.p_flag = False self.s_flag = False - def reset(self, keep_z=False, keep_n=False, keep_h=False, keep_c=False,\ + def reset(self): + self.partial_reset() + + def partial_reset(self, keep_z=False, keep_n=False, keep_h=False, keep_c=False,\ keep_p=False, keep_s=False): if not keep_z: self.z_flag = False @@ -190,12 +193,12 @@ def __init__(self, interrupt, memory): assert isinstance(interrupt, Interrupt) self.interrupt = interrupt - self.memory = memory - self.ime = False - self.halted = False - self.cycles = 0 + self.memory = memory + self.ime = False + self.halted = False + self.cycles = 0 self.ini_registers() - self.rom = [] + self.rom = [] self.reset() def ini_registers(self): @@ -398,7 +401,7 @@ self.push(register.get_hi(), use_cycles) # 2 cycles self.push(register.get_lo(), use_cycles) # 2 cycles - def pop(self): + def pop(self, use_cycles=True): # 1 cycle data = self.memory.read(self.sp.get()) self.sp.inc() # 2 cycles @@ -412,7 +415,7 @@ def double_register_inverse_call(self, getter, register): b = getter(self) # 1 cycle a = getter(self) # 1 cycle - register.set(a, b) # 2 cycles + register.set_hi_lo(a, b) # 2 cycles self.cycles += 1 def call(self, address, use_cycles=True): @@ -428,14 +431,14 @@ setter(getter()) # 1 cycle def load_fetch_register(self, register): - self.ld(self.fetch, register.set) + self.ld(CPUFetchCaller(self).get, RegisterSetCaller(register).set) def store_hl_in_pc(self): # LD PC,HL, 1 cycle - self.ld(self.hl.get, self.pc.set) + self.ld(DoubleRegisterGetCaller(self.hl).get, DoubleRegisterSetCaller(self.pc).set) def fetch_load(self, getter, setter): - self.ld(self.fetch, setter) + self.ld(CPUFetchCaller(self).get, setter) def add_a(self, getter, setter=None): # ALU, 1 cycle @@ -449,9 +452,9 @@ # 2 cycles a=1 added = (self.hl.get() + register.get()) & 0xFFFF # 1 cycle - self.f.reset(keep_z=True) + self.f.partial_reset(keep_z=True) self.f.h_flag_compare((added >> 8), self.hl.get()) - self.f.c_flag_compare(added, self.hl.get()) + self.f.c_flag_compare(added, self.hl.get()) self.hl.set(added) self.cycles -= 1 @@ -534,16 +537,16 @@ def inc(self, getter, setter): # 1 cycle data = (getter() + 1) & 0xFF - self.decInc_flagFinish(data, setter, 0x00) + self.dec_inc_flag_finish(data, setter, 0x00) def dec(self, getter, setter): # 1 cycle data = (getter() - 1) & 0xFF - self.decInc_flagFinish(data, setter, 0x0F) + self.dec_inc_flag_finish(data, setter, 0x0F) self.f.n_flag = True - def decInc_flagFinish(self, data, setter, compare): - self.f.reset(keep_c=True) + def dec_inc_flag_finish(self, data, setter, compare): + self.f.partial_reset(keep_c=True) self.f.z_flag_compare(data) if (data & 0x0F) == compare: self.f.h_flag = True @@ -579,7 +582,8 @@ def rotate_right_circular_a(self): # RRCA 1 cycle - self.rotate_right_circular(self.a.get, self.a.set) + self.rotate_right_circular(RegisterGetCaller(self.a).get, \ + RegisterSetCaller(self.a).set) def rotate_right(self, getter, setter): # 1 cycle @@ -590,7 +594,8 @@ def rotate_right_a(self): # RRA 1 cycle - self.rotate_right(self.a.get, self.a.set) + self.rotate_right(RegisterGetCaller(self.a).get, \ + RegisterSetCaller(self.a).set) def shift_left_arithmetic(self, getter, setter): # 2 cycles @@ -624,7 +629,7 @@ def test_bit(self, getter, setter, n): # 2 cycles - self.f.reset(keep_c=True) + self.f.partial_reset(keep_c=True) self.f.h_flag = True self.f.z_flag = False if (getter() & (1 << n)) == 0: @@ -663,7 +668,7 @@ def load_mem_sp(self): # LD (nnnn),SP 5 cycles address = self.fetch_double_address() # 2 cycles - self.write(address, self.sp.get_lo()) # 2 cycles + self.write(address, self.sp.get_lo()) # 2 cycles self.write((address + 1), self.sp.get_hi()) # 2 cycles self.cycles += 1 @@ -739,7 +744,7 @@ self.a.set((self.a.get() + delta) & 0xFF) # 1 cycle else: self.a.set((self.a.get() - delta) & 0xFF) # 1 cycle - self.f.reset(keep_n=True) + self.f.partial_reset(keep_n=True) if delta >= 0x60: self.f.c_flag = True self.f.z_flag_compare(self.a.get()) @@ -781,11 +786,11 @@ def complement_carry_flag(self): # CCF/SCF - self.f.reset(keep_z=True, keep_c=True) + self.f.partial_reset(keep_z=True, keep_c=True) self.f.c_flag = not self.f.c_flag def set_carry_flag(self): - self.f.reset(keep_z=True) + self.f.partial_reset(keep_z=True) self.f.c_flag = True def nop(self): @@ -831,7 +836,7 @@ # RET 4 cycles lo = self.pop() # 1 cycle hi = self.pop() # 1 cycle - self.pc.set(hi, lo) # 2 cycles + self.pc.set_hi_lo(hi, lo) # 2 cycles def conditional_return(self, cc): # RET cc 2,5 cycles @@ -877,10 +882,72 @@ self.fetch() # ------------------------------------------------------------------------------ + +class CallWrapper(object): + + def get(self, use_cycles=True): + return 0 + + def set(self, value, use_cycles=True): + pass + +class RegisterGetCaller(CallWrapper): + def __init__(self, register): + self.register = register + + def get(self, use_cycles=True): + return self.register.get(use_cycles) + + +class DoubleRegisterGetCaller(RegisterGetCaller): + def __init__(self, register): + self.register = register + + def get(self, use_cycles=True): + return self.register.get(use_cycles) + + +class RegisterSetCaller(CallWrapper): + def __init__(self, register): + self.register = register + + def set(self, value, use_cycles=True): + return self.register.set(value, use_cycles) + +class DoubleRegisterSetCaller(CallWrapper): + def __init__(self, register): + self.register = register + + def set(self, value, use_cycles=True): + return self.register.set(value, use_cycles) + +class CPUPopCaller(CallWrapper): + def __init__(self, cpu): + self.cpu = cpu + + def get(self, use_cycles=True): + return self.cpu.pop(use_cycles) + + +class CPUFetchCaller(CallWrapper): + def __init__(self, cpu): + self.cpu = cpu + + def get(self, use_cycles=True): + return self.cpu.fetch(use_cycles) + +# ------------------------------------------------------------------------------ # OPCODE LOOKUP TABLE GENERATION ----------------------------------------------- -GROUPED_REGISTERS = (CPU.get_b, CPU.get_c, CPU.get_d, CPU.get_e, CPU.get_h, CPU.get_l, CPU.get_hli, CPU.get_a) +GROUPED_REGISTERS = [CPU.get_b, + CPU.get_c, + CPU.get_d, + CPU.get_e, + CPU.get_h, + CPU.get_l, + CPU.get_hli, + CPU.get_a] def create_group_op_codes(table): opCodes =[] @@ -907,11 +974,13 @@ opCode += step return opCodes -def group_lambda(function, registerGetter, value=None): +def group_lambda(function, register_getter, value=None): if value is None: - return lambda s: function(s, registerGetter(s).get, registerGetter(s).set) + return lambda s: function(s, RegisterGetCaller(register_getter(s)).get, \ + RegisterSetCaller(register_getter(s)).set) else: - return lambda s: function(s, registerGetter(s).get, registerGetter(s).set, value) + return lambda s: function(s, RegisterGetCaller(register_getter(s)).get, \ + RegisterSetCaller(register_getter(s)).set, value) def create_load_group_op_codes(): @@ -924,8 +993,9 @@ opCode += 1 return opCodes -def load_group_lambda(storeRegister, loadRegister): - return lambda s: CPU.ld(s, loadRegister(s).get, storeRegister(s).set) +def load_group_lambda(store_register, load_register): + return lambda s: CPU.ld(s, RegisterGetCaller(load_register(s)).get, \ + RegisterSetCaller(store_register(s)).set) def create_register_op_codes(table): @@ -1000,14 +1070,14 @@ (0xF8, CPU.store_fetch_added_sp_in_hl), (0xCB, CPU.fetch_execute), (0xCD, CPU.unconditional_call), - (0xC6, lambda s: CPU.add_a(s, s.fetch)), - (0xCE, lambda s: CPU.add_with_carry(s, s.fetch)), + (0xC6, lambda s: CPU.add_a(s, CPUFetchCaller(s).get)), + (0xCE, lambda s: CPU.add_with_carry(s, CPUFetchCaller(s).get)), (0xD6, CPU.fetch_subtract_a), - (0xDE, lambda s: CPU.subtract_with_carry(s, s.fetch)), - (0xE6, lambda s: CPU.AND(s, s.fetch)), - (0xEE, lambda s: CPU.XOR(s, s.fetch)), - (0xF6, lambda s: CPU.OR(s, s.fetch)), - (0xFE, lambda s: CPU.compare_a(s, s.fetch)), + (0xDE, lambda s: CPU.subtract_with_carry(s, CPUFetchCaller(s).get)), + (0xE6, lambda s: CPU.AND(s, CPUFetchCaller(s).get)), + (0xEE, lambda s: CPU.XOR(s, CPUFetchCaller(s).get)), + (0xF6, lambda s: CPU.OR(s, CPUFetchCaller(s).get)), + (0xFE, lambda s: CPU.compare_a(s, CPUFetchCaller(s).get)), (0xC7, lambda s: CPU.restart(s, 0x00)), (0xCF, lambda s: CPU.restart(s, 0x08)), (0xD7, lambda s: CPU.restart(s, 0x10)), @@ -1015,7 +1085,7 @@ (0xE7, lambda s: CPU.restart(s, 0x20)), (0xEF, lambda s: CPU.restart(s, 0x28)), (0xF7, lambda s: CPU.restart(s, 0x30)), - (0xFF, lambda s: CPU.restart(s, 0x38)), + (0xFF, lambda s: CPU.restart(s, 0x38)) ] REGISTER_GROUP_OP_CODES = [ @@ -1034,9 +1104,21 @@ ] -REGISTER_SET_A = [CPU.get_bc, CPU.get_de, CPU.get_hl, CPU.get_sp] -REGISTER_SET_B = [CPU.get_bc, CPU.get_de, CPU.get_hl, CPU.get_af] -FLAG_REGISTER_SET = [CPU.is_not_z, CPU.is_z, CPU.is_not_c, CPU.is_c] +REGISTER_SET_A = [CPU.get_bc, + CPU.get_de, + CPU.get_hl, + CPU.get_sp] + +REGISTER_SET_B = [CPU.get_bc, + CPU.get_de, + CPU.get_hl, + CPU.get_af] + +FLAG_REGISTER_SET = [CPU.is_not_z, + CPU.is_z, + CPU.is_not_c, + CPU.is_c] + REGISTER_OP_CODES = [ (0x01, 0x10, CPU.fetch_double_register, REGISTER_SET_A), (0x09, 0x10, CPU.add_hl, REGISTER_SET_A), Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboy.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboy.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboy.py Sun May 18 14:38:03 2008 @@ -77,7 +77,7 @@ self.video.reset() self.sound.reset() self.cpu.set_rom(self.cartridge_manager.get_rom()) - self.drawLogo() + self.draw_logo() def get_cycles(self): return min( self.video.get_cycles(), self.serial.get_cycles(), @@ -94,6 +94,7 @@ self.sound.emulate(count) self.joypad.emulate(count) ticks -= count + return 0 def write(self, address, data): receiver = self.get_receiver(address) Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboyImplementation.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboyImplementation.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboyImplementation.py Sun May 18 14:38:03 2008 @@ -38,6 +38,7 @@ print "i" self.emulate(5) time.sleep(0.01) + return 0 # VIDEO DRIVER ----------------------------------------------------------------- @@ -145,6 +146,7 @@ def entry_point(args=None): gameboy = GameBoyImplementation() + # add return statement... # _____ Define and setup target ___ Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/interrupt.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/interrupt.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/interrupt.py Sun May 18 14:38:03 2008 @@ -35,10 +35,10 @@ def create_interrupt_flags(self): self.v_blank = InterruptFlag(True, constants.VBLANK, 0x40) - self.lcd = InterruptFlag(False, constants.LCD, 0x48) - self.timer = InterruptFlag(False, constants.TIMER, 0x50) - self.serial = InterruptFlag(False, constants.SERIAL, 0x58) - self.joypad = InterruptFlag(False, constants.JOYPAD, 0x60) + self.lcd = InterruptFlag(False, constants.LCD, 0x48) + self.timer = InterruptFlag(False, constants.TIMER, 0x50) + self.serial = InterruptFlag(False, constants.SERIAL, 0x58) + self.joypad = InterruptFlag(False, constants.JOYPAD, 0x60) def create_flag_list(self): self.interrupt_flags = [ Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/joypad.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/joypad.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/joypad.py Sun May 18 14:38:03 2008 @@ -70,21 +70,21 @@ self.reset() def create_buttons(self): - self.up = Button(constants.BUTTON_UP) - self.right = Button(constants.BUTTON_RIGHT) - self.down = Button(constants.BUTTON_DOWN) - self.left = Button(constants.BUTTON_LEFT) - self.start = Button(constants.BUTTON_START) + self.up = Button(constants.BUTTON_UP) + self.right = Button(constants.BUTTON_RIGHT) + self.down = Button(constants.BUTTON_DOWN) + self.left = Button(constants.BUTTON_LEFT) + self.start = Button(constants.BUTTON_START) self.select = Button(constants.BUTTON_SELECT) - self.a = Button(constants.BUTTON_A) - self.b = Button(constants.BUTTON_B) + self.a = Button(constants.BUTTON_A) + self.b = Button(constants.BUTTON_B) self.add_opposite_buttons() self.create_button_groups() def add_opposite_buttons(self): - self.up.opposite_button = self.down - self.down.opposite_button = self.up - self.left.opposite_button = self.right + self.up.opposite_button = self.down + self.down.opposite_button = self.up + self.left.opposite_button = self.right self.right.opposite_button = self.left def create_button_groups(self): Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cpu.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cpu.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cpu.py Sun May 18 14:38:03 2008 @@ -381,7 +381,7 @@ # ld_BCi_A def test_0x02(): cpu = get_cpu(); - cpu.bc.set(0xC2, 0x23); + cpu.bc.set_hi_lo(0xC2, 0x23); cpu.a.set(0x12); cycle_test(cpu, 0x02, 2); assert cpu.read(cpu.bc.get()) == cpu.a.get() @@ -401,7 +401,7 @@ # ld_DEi_A def test_0x12(): cpu = get_cpu(); - cpu.de.set(0xC2, 0x23); + cpu.de.set_hi_lo(0xC2, 0x23); cpu.a.set(0x12); cycle_test(cpu, 0x12, 2); assert cpu.read(cpu.de.get()) == cpu.a.get() @@ -420,7 +420,7 @@ # ldi_HLi_A def test_0x22(): cpu = get_cpu(); - cpu.hl.set(0xCD, 0xEF); + cpu.hl.set_hi_lo(0xCD, 0xEF); cpu.a.set(0x12); cycle_test(cpu, 0x22, 2); assert cpu.read(0xCDEF) == cpu.a.get() @@ -429,7 +429,7 @@ # ldd_HLi_A def test_0x32(): cpu = get_cpu(); - cpu.hl.set(0xCD, 0xEF); + cpu.hl.set_hi_lo(0xCD, 0xEF); cpu.a.set(0x12); cycle_test(cpu, 0x32, 2); assert cpu.read(0xCDEF) == cpu.a.get() Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_register.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_register.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_register.py Sun May 18 14:38:03 2008 @@ -103,7 +103,7 @@ valueHi = 0x12 valueLo = 0x34 oldCycles = register.cpu.cycles - register.set(valueHi, valueLo) + register.set_hi_lo(valueHi, valueLo) assert oldCycles-register.cpu.cycles == 2 assert register.get_hi() == valueHi assert register.get_lo() == valueLo Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/timer.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/timer.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/timer.py Sun May 18 14:38:03 2008 @@ -121,5 +121,5 @@ pass def get_time(self): - return time.time() + return int(time.time()*1000) Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/video.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/video.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/video.py Sun May 18 14:38:03 2008 @@ -540,7 +540,7 @@ self.line[pos] |= color | mask def draw_overlapped_object_tile(self, x, address, flags): - self.draw_object(self.setOverlappedObjectLine, x, address, flags) + self.draw_object(self.set_overlapped_object_line, x, address, flags) def set_overlapped_object_line(self, pos, color, mask): self.line[pos] = (self.line[pos] & 0x0101) | color | mask From tverwaes at codespeak.net Sun May 18 14:51:28 2008 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Sun, 18 May 2008 14:51:28 +0200 (CEST) Subject: [pypy-svn] r54884 - pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk Message-ID: <20080518125128.BF967169E13@codespeak.net> Author: tverwaes Date: Sun May 18 14:51:27 2008 New Revision: 54884 Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/interpreter.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/wrapper.py Log: (cfbolz, tverwaes) adding tests for processwrapper Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/interpreter.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/interpreter.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/interpreter.py Sun May 18 14:51:27 2008 @@ -40,9 +40,9 @@ def store_w_active_context(self, w_context): # We can only interpret contexts of which we know the type already - s_ctx = w_context.as_context_get_shadow() - assert (isinstance(s_ctx, MethodContextShadow) or - isinstance(s_ctx, BlockContextShadow)) + #s_ctx = w_context.as_context_get_shadow() + #assert (isinstance(s_ctx, MethodContextShadow) or + # isinstance(s_ctx, BlockContextShadow)) if self._s_active_context is not None: self._s_active_context.unnotify(self) self._s_active_context = None Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/wrapper.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/wrapper.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/wrapper.py Sun May 18 14:51:27 2008 @@ -38,9 +38,12 @@ class ProcessWrapper(LinkWrapper): suspended_context, store_suspended_context = make_getter_setter(1) - priority = make_getter(2) my_list, store_my_list = make_getter_setter(3) + def priority(self): + w_priority = self.read(2) + return utility.unwrap_int(w_priority) + def put_to_sleep(self): sched = scheduler() priority = self.priority() @@ -52,7 +55,9 @@ sched = scheduler() w_old_process = sched.active_process() sched.store_active_process(self.w_self) - ProcessWrapper(w_old_process).store_suspended_context(interp.w_active_context()) + old_process = ProcessWrapper(w_old_process) + old_process.store_suspended_context(interp.w_active_context()) + old_process.put_to_sleep() interp.store_w_active_context(self.suspended_context()) self.store_suspended_context(objtable.w_nil) @@ -62,10 +67,9 @@ active_priority = active_process.priority() priority = self.priority() if priority > active_priority: - active_process.put_to_sleep() self.activate(interp) else: - self.put_to_sleep(process) + self.put_to_sleep() class LinkedListWrapper(Wrapper): @@ -109,8 +113,7 @@ priority_list = make_getter(0) active_process, store_active_process = make_getter_setter(1) - def get_process_list(self, w_priority): - priority = utility.unwrap_int(w_priority) + def get_process_list(self, priority): lists = self.priority_list() return ProcessListWrapper(Wrapper(lists).read(priority)) From tverwaes at codespeak.net Sun May 18 14:52:32 2008 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Sun, 18 May 2008 14:52:32 +0200 (CEST) Subject: [pypy-svn] r54885 - pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test Message-ID: <20080518125232.A6F4C169E13@codespeak.net> Author: tverwaes Date: Sun May 18 14:52:31 2008 New Revision: 54885 Added: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_wrapper.py Log: (tverwaes, cfbolz): thank god nobody is watching our commits, otherwise she would have thought that we didn't write any tests. Added: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_wrapper.py ============================================================================== --- (empty file) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_wrapper.py Sun May 18 14:52:31 2008 @@ -0,0 +1,180 @@ +import py +from pypy.lang.smalltalk import wrapper +from pypy.lang.smalltalk import model +from pypy.lang.smalltalk import objtable, utility +from pypy.lang.smalltalk import interpreter + +def test_simpleread(): + w_o = model.W_PointersObject(None, 2) + w = wrapper.Wrapper(w_o) + w_o._vars[0] = "hello" + assert w.read(0) == "hello" + w.write(1, "b") + assert w.read(1) == "b" + py.test.raises(IndexError, "w.read(2)") + py.test.raises(IndexError, "w.write(2, \"test\")") + +def test_accessor_generators(): + w_o = model.W_PointersObject(None, 1) + w = wrapper.LinkWrapper(w_o) + w_o._vars[0] = "hello" + assert w.next_link() == "hello" + w.store_next_link("boe") + assert w.next_link() == "boe" + +def link(w_next='foo'): + w_object = model.W_PointersObject(None, 1) + wrapper.LinkWrapper(w_object).store_next_link(w_next) + return w_object + +def test_linked_list(): + w_object = model.W_PointersObject(None,2) + w_last = link(objtable.w_nil) + w_lb1 = link(w_last) + w_lb2 = link(w_lb1) + w_lb3 = link(w_lb2) + w_lb4 = link(w_lb3) + w_first = link(w_lb4) + linkedlist = wrapper.LinkedListWrapper(w_object) + linkedlist.store_first_link(w_first) + linkedlist.store_last_link(w_last) + assert w_first is linkedlist.first_link() + assert w_last is linkedlist.last_link() + assert linkedlist.remove_first_link_of_list() is w_first + assert linkedlist.remove_first_link_of_list() is w_lb4 + assert linkedlist.remove_first_link_of_list() is w_lb3 + assert not linkedlist.is_empty_list() + assert linkedlist.remove_first_link_of_list() is w_lb2 + assert linkedlist.remove_first_link_of_list() is w_lb1 + assert linkedlist.remove_first_link_of_list() is w_last + assert linkedlist.is_empty_list() + linkedlist.add_last_link(w_first) + assert linkedlist.first_link() is w_first + assert linkedlist.last_link() is w_first + linkedlist.add_last_link(w_last) + assert linkedlist.first_link() is w_first + assert linkedlist.last_link() is w_last + +def new_process(w_next=objtable.w_nil, + w_my_list=objtable.w_nil, + w_suspended_context=objtable.w_nil, + priority=0): + w_priority = utility.wrap_int(priority) + w_process = model.W_PointersObject(None, 4) + process = wrapper.ProcessWrapper(w_process) + process.store_next_link(w_next) + process.store_my_list(w_my_list) + process.store_suspended_context(w_suspended_context) + process.write(2, w_priority) + return process + +def new_processlist(processes_w=[]): + w_processlist = model.W_PointersObject(None, 2) + w_first = objtable.w_nil + w_last = objtable.w_nil + for w_process in processes_w[::-1]: + w_first = newprocess(w_first, w_processlist).w_self + if w_last is objtable.w_nil: + w_last = w_first + pl = wrapper.ProcessListWrapper(w_processlist) + pl.store_first_link(w_first) + pl.store_last_link(w_last) + return pl + +def new_prioritylist(prioritydict=None): + if prioritydict is not None: + maxpriority = max(prioritydict.keys()) + else: + maxpriority = 5 + prioritydict = {} + w_prioritylist = model.W_PointersObject(None, maxpriority) + prioritylist = wrapper.Wrapper(w_prioritylist) + for i in range(maxpriority): + prioritylist.write(i, new_processlist(prioritydict.get(i, [])).w_self) + + return prioritylist + +def new_scheduler(w_process=objtable.w_nil, prioritydict=None): + priority_list = new_prioritylist(prioritydict) + w_scheduler = model.W_PointersObject(None, 2) + scheduler = wrapper.SchedulerWrapper(w_scheduler) + scheduler.store_active_process(w_process) + scheduler.write(0, priority_list.w_self) + return scheduler + + + +class TestScheduler(object): + def setup_method(self, meth): + self.old_scheduler = wrapper.scheduler + wrapper.scheduler = lambda: scheduler + scheduler = new_scheduler() + + def teardown_method(self, meth): + wrapper.scheduler = self.old_scheduler + + def test_suspend(self): + process = new_process(priority=2) + process.put_to_sleep() + process_list = wrapper.scheduler().get_process_list(2) + assert process_list.first_link() is process_list.last_link() + assert process_list.first_link() is process.w_self + + def test_activate(self): + interp = interpreter.Interpreter() + scheduler = wrapper.scheduler() + process = new_process(priority=2, w_suspended_context=objtable.w_false) + process.put_to_sleep() + old_process = new_process(priority=3) + scheduler.store_active_process(old_process.w_self) + interp.store_w_active_context(objtable.w_true) + process.activate(interp) + + assert old_process.suspended_context() is objtable.w_true + priority_list = wrapper.scheduler().get_process_list(old_process.priority()) + assert priority_list.first_link() is old_process.w_self + assert interp.w_active_context() is objtable.w_false + assert scheduler.active_process() is process.w_self + priority_list = wrapper.scheduler().get_process_list(process.priority()) + assert priority_list.first_link() is priority_list.last_link() + # activate does not remove the process from the process_list. + # The caller of activate is responsible + assert priority_list.first_link() is process.w_self + + def test_resume(self): + interp = interpreter.Interpreter() + scheduler = wrapper.scheduler() + process = new_process(priority=4, w_suspended_context=objtable.w_false) + process.put_to_sleep() + old_process = new_process(priority=2) + scheduler.store_active_process(old_process.w_self) + interp.store_w_active_context(objtable.w_true) + + process.resume(interp) + + assert old_process.suspended_context() is objtable.w_true + priority_list = wrapper.scheduler().get_process_list(old_process.priority()) + assert priority_list.first_link() is old_process.w_self + assert interp.w_active_context() is objtable.w_false + assert scheduler.active_process() is process.w_self + priority_list = wrapper.scheduler().get_process_list(process.priority()) + assert priority_list.first_link() is priority_list.last_link() + # activate does not remove the process from the process_list. + # The caller of activate is responsible + assert priority_list.first_link() is process.w_self + + # Does not reactivate old_process because lower priority + old_process.resume(interp) + + assert old_process.suspended_context() is objtable.w_true + priority_list = wrapper.scheduler().get_process_list(old_process.priority()) + assert priority_list.first_link() is old_process.w_self + assert interp.w_active_context() is objtable.w_false + assert scheduler.active_process() is process.w_self + priority_list = wrapper.scheduler().get_process_list(process.priority()) + assert priority_list.first_link() is priority_list.last_link() + # activate does not remove the process from the process_list. + # The caller of activate is responsible + assert priority_list.first_link() is process.w_self + + From tverwaes at codespeak.net Sun May 18 15:17:32 2008 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Sun, 18 May 2008 15:17:32 +0200 (CEST) Subject: [pypy-svn] r54886 - pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test Message-ID: <20080518131732.C6A9F2A0180@codespeak.net> Author: tverwaes Date: Sun May 18 15:17:30 2008 New Revision: 54886 Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_wrapper.py Log: (cfbolz, tverwaes) refactored shared test_code Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_wrapper.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_wrapper.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_wrapper.py Sun May 18 15:17:30 2008 @@ -120,6 +120,20 @@ assert process_list.first_link() is process_list.last_link() assert process_list.first_link() is process.w_self + def old_new_process_consistency(self, process, old_process, interp, + old_active_context, new_active_context): + scheduler = wrapper.scheduler() + assert old_process.suspended_context() is old_active_context + priority_list = scheduler.get_process_list(old_process.priority()) + assert priority_list.first_link() is old_process.w_self + assert interp.w_active_context() is new_active_context + assert scheduler.active_process() is process.w_self + priority_list = wrapper.scheduler().get_process_list(process.priority()) + assert priority_list.first_link() is priority_list.last_link() + # activate does not remove the process from the process_list. + # The caller of activate is responsible + assert priority_list.first_link() is process.w_self + def test_activate(self): interp = interpreter.Interpreter() scheduler = wrapper.scheduler() @@ -129,18 +143,10 @@ scheduler.store_active_process(old_process.w_self) interp.store_w_active_context(objtable.w_true) process.activate(interp) - - assert old_process.suspended_context() is objtable.w_true - priority_list = wrapper.scheduler().get_process_list(old_process.priority()) - assert priority_list.first_link() is old_process.w_self - assert interp.w_active_context() is objtable.w_false - assert scheduler.active_process() is process.w_self - priority_list = wrapper.scheduler().get_process_list(process.priority()) - assert priority_list.first_link() is priority_list.last_link() - # activate does not remove the process from the process_list. - # The caller of activate is responsible - assert priority_list.first_link() is process.w_self + self.old_new_process_consistency(process, old_process, interp, + objtable.w_true, objtable.w_false) + def test_resume(self): interp = interpreter.Interpreter() scheduler = wrapper.scheduler() @@ -151,30 +157,12 @@ interp.store_w_active_context(objtable.w_true) process.resume(interp) - - assert old_process.suspended_context() is objtable.w_true - priority_list = wrapper.scheduler().get_process_list(old_process.priority()) - assert priority_list.first_link() is old_process.w_self - assert interp.w_active_context() is objtable.w_false - assert scheduler.active_process() is process.w_self - priority_list = wrapper.scheduler().get_process_list(process.priority()) - assert priority_list.first_link() is priority_list.last_link() - # activate does not remove the process from the process_list. - # The caller of activate is responsible - assert priority_list.first_link() is process.w_self + self.old_new_process_consistency(process, old_process, interp, + objtable.w_true, objtable.w_false) # Does not reactivate old_process because lower priority old_process.resume(interp) - - assert old_process.suspended_context() is objtable.w_true - priority_list = wrapper.scheduler().get_process_list(old_process.priority()) - assert priority_list.first_link() is old_process.w_self - assert interp.w_active_context() is objtable.w_false - assert scheduler.active_process() is process.w_self - priority_list = wrapper.scheduler().get_process_list(process.priority()) - assert priority_list.first_link() is priority_list.last_link() - # activate does not remove the process from the process_list. - # The caller of activate is responsible - assert priority_list.first_link() is process.w_self + self.old_new_process_consistency(process, old_process, interp, + objtable.w_true, objtable.w_false) From cami at codespeak.net Sun May 18 16:23:10 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Sun, 18 May 2008 16:23:10 +0200 (CEST) Subject: [pypy-svn] r54888 - in pypy/branch/gameboy-emulator/pypy/lang/gameboy: . test Message-ID: <20080518142310.C4EFC169DFC@codespeak.net> Author: cami Date: Sun May 18 16:23:08 2008 New Revision: 54888 Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cpu.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/video.py Log: added CallWrappers in Video Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py Sun May 18 16:23:08 2008 @@ -92,7 +92,7 @@ # ------------------------------------------------------------------------------ -class ImmediatePseudoRegister(iRegister): +class ImmediatePseudoRegister(Register): def __init__(self, cpu, hl): assert isinstance(cpu, CPU) @@ -389,7 +389,7 @@ return (hi << 8) + lo def fetch_double_register(self, register): - self.double_register_inverse_call(CPU.fetch, register) + self.double_register_inverse_call(CPUFetchCaller(self).get, register) def push(self, data, use_cycles=True): # Stack, 2 cycles @@ -410,11 +410,11 @@ def pop_double_register(self, register): # 3 cycles - self.double_register_inverse_call(CPU.pop, register) + self.double_register_inverse_call(CPUPopCaller(self).get, register) def double_register_inverse_call(self, getter, register): - b = getter(self) # 1 cycle - a = getter(self) # 1 cycle + b = getter() # 1 cycle + a = getter() # 1 cycle register.set_hi_lo(a, b) # 2 cycles self.cycles += 1 @@ -435,7 +435,8 @@ def store_hl_in_pc(self): # LD PC,HL, 1 cycle - self.ld(DoubleRegisterGetCaller(self.hl).get, DoubleRegisterSetCaller(self.pc).set) + self.ld(DoubleRegisterGetCaller(self.hl).get, \ + DoubleRegisterSetCaller(self.pc).set) def fetch_load(self, getter, setter): self.ld(CPUFetchCaller(self).get, setter) @@ -561,7 +562,8 @@ def rotate_left_circular_a(self): # RLCA rotate_left_circular_a 1 cycle - self.rotate_left_circular(self.a.get, self.a.set) + self.rotate_left_circular(RegisterGetCaller(self.a).get, \ + RegisterSetCaller(self.a).set) def rotate_left(self, getter, setter): # 1 cycle @@ -572,7 +574,8 @@ def rotate_left_a(self): # RLA 1 cycle - self.rotate_left(self.a.get, self.a.set) + self.rotate_left(RegisterGetCaller(self.a).get, \ + RegisterSetCaller(self.a).set) def rotate_right_circular(self, getter, setter): data = getter() @@ -914,6 +917,7 @@ def set(self, value, use_cycles=True): return self.register.set(value, use_cycles) + class DoubleRegisterSetCaller(CallWrapper): def __init__(self, register): self.register = register @@ -921,6 +925,7 @@ def set(self, value, use_cycles=True): return self.register.set(value, use_cycles) + class CPUPopCaller(CallWrapper): def __init__(self, cpu): self.cpu = cpu @@ -977,12 +982,11 @@ def group_lambda(function, register_getter, value=None): if value is None: return lambda s: function(s, RegisterGetCaller(register_getter(s)).get, \ - RegisterSetCaller(register_getter(s)).set) + RegisterSetCaller(register_getter(s)).set) else: - return lambda s: function(s, RegisterGetCaller(register_getter(s)).get, \ - RegisterSetCaller(register_getter(s)).set, value) - - + return lambda s: function(s, RegisterGetCaller(register_getter(s)).get, \ + RegisterSetCaller(register_getter(s)).set, value) + def create_load_group_op_codes(): opCodes = [] opCode = 0x40 Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cpu.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cpu.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cpu.py Sun May 18 16:23:08 2008 @@ -175,7 +175,7 @@ for entry in grouped: assert len(entry) == 2 assert entry[0] == opCode - assert entry[1].func_name == "" + #assert entry[1].func_name == "" #assert entry[1].func_closure[0].cell_contents == func opCode += step Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/video.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/video.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/video.py Sun May 18 16:23:08 2008 @@ -6,6 +6,29 @@ from pypy.lang.gameboy import constants from pypy.lang.gameboy.ram import iMemory + + +class VideoCallWraper(object): + def call(self, pos, color, mask): + pass + + +class set_overlapped_object_line_call_wrapper(VideoCallWraper): + def __init__(self, video): + self.video = video + + def call(self, pos, color, mask): + self.video. set_overlapped_object_line(pos, color, mask) + + +class set_tile_line_call_wrapper(VideoCallWraper): + def __init__(self, video): + self.video = video + + def call(self, pos, color, mask): + self.video.set_tile_line(pos, color, mask) + + class Video(iMemory): #frames = 0 #frame_skip = 0 @@ -496,7 +519,7 @@ pattern += (self.vram[address + 1] & 0xFF) << 8 return pattern - def draw_object(self, setter, x, address, flags): + def draw_object(self, caller, x, address, flags): pattern = self.get_pattern(address) mask = 0 # priority @@ -506,27 +529,27 @@ if (flags & 0x10) != 0: mask |= 0x0004 if (flags & 0x20) != 0: - self.draw_object_normal(x, pattern, mask, setter) + self.draw_object_normal(x, pattern, mask, caller) else: - self.draw_object_flipped(x, pattern, mask, setter) + self.draw_object_flipped(x, pattern, mask, caller) - def draw_object_normal(self, x, pattern, mask, setter): + def draw_object_normal(self, x, pattern, mask, caller): for i in range(0, 7): color = pattern >> (6-i) if (color & 0x0202) != 0: - setter(x+1, color, mask) + caller(x+1, color, mask) color = pattern << 1 if (color & 0x0202) != 0: - setter(x+7, color, mask) + caller(x+7, color, mask) - def draw_object_flipped(self, x, pattern, mask, setter): + def draw_object_flipped(self, x, pattern, mask, caller): color = pattern << 1 if (color & 0x0202) != 0: - setter(x, color, mask) + caller(x, color, mask) for i in range(0, 7): color = pattern >> i if (color & 0x0202) != 0: - setter(x + i + 1, color, mask) + caller(x + i + 1, color, mask) def draw_tile(self, x, address): pattern = self.get_pattern(address) @@ -534,13 +557,15 @@ self.line[x + i] = (pattern >> (7-i)) & 0x0101 def draw_object_tile(self, x, address, flags): - self.draw_object(self.set_tile_line, x, address, flags) + self.draw_object(set_tile_line_call_wrapper(self).call, x, address, \ + flags) def set_tile_line(self, pos, color, mask): self.line[pos] |= color | mask def draw_overlapped_object_tile(self, x, address, flags): - self.draw_object(self.set_overlapped_object_line, x, address, flags) + self.draw_object(set_overlapped_object_line_call_wrapper(self).call, \ + x, address, flags) def set_overlapped_object_line(self, pos, color, mask): self.line[pos] = (self.line[pos] & 0x0101) | color | mask From fijal at codespeak.net Sun May 18 16:40:04 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 18 May 2008 16:40:04 +0200 (CEST) Subject: [pypy-svn] r54890 - pypy/branch/hybrid-io/pypy/rpython/lltypesystem Message-ID: <20080518144004.00F21169E42@codespeak.net> Author: fijal Date: Sun May 18 16:40:03 2008 New Revision: 54890 Modified: pypy/branch/hybrid-io/pypy/rpython/lltypesystem/llmemory.py Log: raw_free for raw_realloc Modified: pypy/branch/hybrid-io/pypy/rpython/lltypesystem/llmemory.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/lltypesystem/llmemory.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/lltypesystem/llmemory.py Sun May 18 16:40:03 2008 @@ -696,11 +696,13 @@ def raw_realloc_grow(addr, old_size, size): new_area = size._raw_malloc([], zero=False) raw_memcopy(addr, new_area, old_size) + raw_free(addr) return new_area def raw_realloc_shrink(addr, old_size, size): new_area = size._raw_malloc([], zero=False) raw_memcopy(addr, new_area, size) + raw_free(addr) return new_area def raw_free(adr): From arigo at codespeak.net Sun May 18 17:11:37 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 18 May 2008 17:11:37 +0200 (CEST) Subject: [pypy-svn] r54891 - in pypy/dist/pypy: config module/readline rpython/tool rpython/tool/test tool tool/test translator/tool Message-ID: <20080518151137.EB6812A017B@codespeak.net> Author: arigo Date: Sun May 18 17:11:35 2008 New Revision: 54891 Modified: pypy/dist/pypy/config/pypyoption.py pypy/dist/pypy/module/readline/c_readline.py pypy/dist/pypy/rpython/tool/rffi_platform.py pypy/dist/pypy/rpython/tool/test/test_rffi_platform.py pypy/dist/pypy/tool/gcc_cache.py pypy/dist/pypy/tool/test/test_gcc_cache.py pypy/dist/pypy/translator/tool/cbuild.py Log: Whack whack whack until the logic for skipping modules from --allworkingmodules if the C code snippets cannot be compiled. In this attempt, we should see the whole C compiler output when running translate.py. Modified: pypy/dist/pypy/config/pypyoption.py ============================================================================== --- pypy/dist/pypy/config/pypyoption.py (original) +++ pypy/dist/pypy/config/pypyoption.py Sun May 18 17:11:35 2008 @@ -56,6 +56,7 @@ module_import_dependencies = { # no _rawffi if importing pypy.rlib.libffi raises ImportError + # or CompilationError "_rawffi": ["pypy.rlib.libffi"], } @@ -63,16 +64,17 @@ if modname in module_import_dependencies: modlist = module_import_dependencies[modname] def validator(config): + from pypy.rpython.tool.rffi_platform import CompilationError try: for name in modlist: __import__(name) - except ImportError, e: - err = "%s: %s" % (e.__class__.__name__, e) + except (ImportError, CompilationError), e: + errcls = e.__class__.__name__ config.add_warning( "The module %r is disabled\n" % (modname,) + - "because importing %s raised\n" % (name,) + - err) - raise ConfigError("--withmod-%s: %s" % (modname, err)) + "because importing %s raised %s\n" % (name, errcls) + + str(e)) + raise ConfigError("--withmod-%s: %s" % (modname, errcls)) return validator else: return None Modified: pypy/dist/pypy/module/readline/c_readline.py ============================================================================== --- pypy/dist/pypy/module/readline/c_readline.py (original) +++ pypy/dist/pypy/module/readline/c_readline.py Sun May 18 17:11:35 2008 @@ -8,15 +8,18 @@ # we also need to link with some variant of curses or libtermcap. # We follow the logic of CPython below. def try_with_lib(extralibs, **kwds): + global most_recent_error # at least on Gentoo Linux, readline.h doesn't compile if stdio.h is not # included before eci = ExternalCompilationInfo( includes = ["stdio.h", "readline/readline.h", "readline/history.h"], libraries = extralibs + ['readline'], ) - if platform.check_eci(eci): + try: + platform.verify_eci(eci) return eci - else: + except platform.CompilationError, e: + most_recent_error = e return None eci = (try_with_lib([]) or @@ -25,7 +28,7 @@ try_with_lib(['curses']) or try_with_lib(['termcap'], library_dirs=['/usr/lib/termcap'])) if eci is None: - raise Exception("cannot find how to link to the readline library") + raise most_recent_error # ____________________________________________________________ Modified: pypy/dist/pypy/rpython/tool/rffi_platform.py ============================================================================== --- pypy/dist/pypy/rpython/tool/rffi_platform.py (original) +++ pypy/dist/pypy/rpython/tool/rffi_platform.py Sun May 18 17:11:35 2008 @@ -6,6 +6,7 @@ from pypy.rpython.lltypesystem import llmemory from pypy.tool.gcc_cache import build_executable_cache, try_compile_cache from pypy.translator.tool.cbuild import ExternalCompilationInfo +from pypy.translator.tool.cbuild import CompilationError from pypy.tool.udir import udir import distutils @@ -48,12 +49,13 @@ HAS = Has(name) return configure(CConfig)['HAS'] -def check_eci(eci): - """Check if a given ExternalCompilationInfo compiles and links.""" +def verify_eci(eci): + """Check if a given ExternalCompilationInfo compiles and links. + If not, raises CompilationError.""" class CConfig: _compilation_info_ = eci WORKS = Works() - return configure(CConfig)['WORKS'] + configure(CConfig) def sizeof(name, eci, **kwds): class CConfig: @@ -150,8 +152,8 @@ self.f.write(question + "\n") self.close() eci = self.config._compilation_info_ - return try_compile_cache([self.path], eci) - + try_compile_cache([self.path], eci) + def configure(CConfig): """Examine the local system by running the C compiler. The CConfig class contains CConfigEntry attribues that describe @@ -445,11 +447,15 @@ self.name = name def question(self, ask_gcc): - return ask_gcc(self.name + ';') + try: + ask_gcc(self.name + ';') + return True + except CompilationError: + return False class Works(CConfigSingleEntry): def question(self, ask_gcc): - return ask_gcc("") + ask_gcc("") class SizeOf(CConfigEntry): """An entry in a CConfig class that stands for Modified: pypy/dist/pypy/rpython/tool/test/test_rffi_platform.py ============================================================================== --- pypy/dist/pypy/rpython/tool/test/test_rffi_platform.py (original) +++ pypy/dist/pypy/rpython/tool/test/test_rffi_platform.py Sun May 18 17:11:35 2008 @@ -218,11 +218,12 @@ # has() should also not crash if it is given an invalid #include assert not rffi_platform.has("x", "#include ") -def test_check_eci(): +def test_verify_eci(): eci = ExternalCompilationInfo() - assert rffi_platform.check_eci(eci) + rffi_platform.verify_eci(eci) eci = ExternalCompilationInfo(libraries=['some_name_that_doesnt_exist_']) - assert not rffi_platform.check_eci(eci) + py.test.raises(rffi_platform.CompilationError, + rffi_platform.verify_eci, eci) def test_sizeof(): assert rffi_platform.sizeof("char", ExternalCompilationInfo()) == 1 Modified: pypy/dist/pypy/tool/gcc_cache.py ============================================================================== --- pypy/dist/pypy/tool/gcc_cache.py (original) +++ pypy/dist/pypy/tool/gcc_cache.py Sun May 18 17:11:35 2008 @@ -1,6 +1,8 @@ from pypy.tool.autopath import pypydir -from pypy.translator.tool.cbuild import build_executable, ExternalCompilationInfo +from pypy.translator.tool.cbuild import build_executable +from pypy.translator.tool.cbuild import ExternalCompilationInfo +from pypy.translator.tool.cbuild import CompilationError import md5 import py import distutils @@ -27,13 +29,19 @@ def try_compile_cache(c_files, eci): path = cache_file_path(c_files, eci, 'try_compile_cache') try: - return eval(path.read()) + data = path.read() except py.error.Error: + data = '' + if not (data.startswith('True') or data.startswith('FAIL\n')): try: build_executable(c_files, eci) - result = True - except (distutils.errors.CompileError, - distutils.errors.LinkError): - result = False - path.write(repr(result)) - return result + data = 'True' + except CompilationError, e: + data = 'FAIL\n%s\n' % (e,) + path.write(data) + if data.startswith('True'): + return True + else: + assert data.startswith('FAIL\n') + msg = data[len('FAIL\n'):] + raise CompilationError(msg.strip()) Modified: pypy/dist/pypy/tool/test/test_gcc_cache.py ============================================================================== --- pypy/dist/pypy/tool/test/test_gcc_cache.py (original) +++ pypy/dist/pypy/tool/test/test_gcc_cache.py Sun May 18 17:11:35 2008 @@ -28,6 +28,11 @@ assert build_executable_cache([f], eci) == "3\n" eci2 = ExternalCompilationInfo(include_dirs=[str(dir2)]) assert build_executable_cache([f], eci2) == "42\n" + f.write("#error BOOM\n") + err = py.test.raises(CompilationError, build_executable_cache, [f], eci2) + print '<<<' + print err + print '>>>' def test_gcc_ask(): f = udir.join("y.c") @@ -53,4 +58,7 @@ assert try_compile_cache([f], eci) assert build_executable_cache([f], eci) == "hello\n" eci2 = ExternalCompilationInfo(include_dirs=[str(dir2)]) - assert not try_compile_cache([f], eci2) + err = py.test.raises(CompilationError, try_compile_cache, [f], eci2) + print '<<<' + print err + print '>>>' Modified: pypy/dist/pypy/translator/tool/cbuild.py ============================================================================== --- pypy/dist/pypy/translator/tool/cbuild.py (original) +++ pypy/dist/pypy/translator/tool/cbuild.py Sun May 18 17:11:35 2008 @@ -463,7 +463,10 @@ finally: compiler.compile_extra.pop() compiler.link_extra.pop() - + +class CompilationError(Exception): + pass + class CCompiler: def __init__(self, cfilenames, eci, outputfilename=None, @@ -507,6 +510,7 @@ self.eci = eci def build(self, noerr=False): + import distutils.errors basename = self.outputfilename.new(ext='') data = '' try: @@ -537,6 +541,13 @@ fdump = basename.new(ext='errors').open("w") fdump.write(data) fdump.close() + except (distutils.errors.CompileError, + distutils.errors.LinkError), e: + data = data.rstrip() + if data: + data += '\n' + data += str(e) + raise CompilationError(data) except: if not noerr: print >>sys.stderr, data @@ -577,7 +588,6 @@ return str(compiler.outputfilename) def check_boehm_presence(): - import distutils.errors from pypy.tool.udir import udir try: cfile = udir.join('check_boehm.c') @@ -596,14 +606,12 @@ else: eci = ExternalCompilationInfo(libraries=['gc']) build_executable([cfname], eci, noerr=True) - except (distutils.errors.CompileError, - distutils.errors.LinkError): + except CompilationError: return False else: return True def check_under_under_thread(): - import distutils.errors from pypy.tool.udir import udir cfile = py.path.local(autopath.this_dir).join('__thread_test.c') fsource = cfile.open('r') @@ -617,8 +625,7 @@ exe = build_executable([str(cfile)], ExternalCompilationInfo(), noerr=True) py.process.cmdexec(exe) - except (distutils.errors.CompileError, - distutils.errors.LinkError, + except (CompilationError, py.error.Error): return False else: From arigo at codespeak.net Sun May 18 17:14:58 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 18 May 2008 17:14:58 +0200 (CEST) Subject: [pypy-svn] r54892 - pypy/dist/pypy/rlib/rsdl Message-ID: <20080518151458.E1EB22A017B@codespeak.net> Author: arigo Date: Sun May 18 17:14:58 2008 New Revision: 54892 Modified: pypy/dist/pypy/rlib/rsdl/constants.py Log: Untabiffy. Modified: pypy/dist/pypy/rlib/rsdl/constants.py ============================================================================== --- pypy/dist/pypy/rlib/rsdl/constants.py (original) +++ pypy/dist/pypy/rlib/rsdl/constants.py Sun May 18 17:14:58 2008 @@ -79,175 +79,175 @@ '': [ # constants with no prefix in C "TIMER_RESOLUTION", - "AUDIO_U8", - "AUDIO_S8", - "AUDIO_U16LSB", - "AUDIO_S16LSB", - "AUDIO_U16MSB", - "AUDIO_S16MSB", - "AUDIO_U16", - "AUDIO_S16", - "AUDIO_U16SYS", - "AUDIO_S16SYS", - - "KMOD_NONE", - "KMOD_LSHIFT", - "KMOD_RSHIFT", - "KMOD_LCTRL", - "KMOD_RCTRL", - "KMOD_LALT", - "KMOD_RALT", - "KMOD_LMETA", - "KMOD_RMETA", - "KMOD_NUM", - "KMOD_CAPS", - "KMOD_MODE", - - "KMOD_CTRL", - "KMOD_SHIFT", - "KMOD_ALT", - "KMOD_META", + "AUDIO_U8", + "AUDIO_S8", + "AUDIO_U16LSB", + "AUDIO_S16LSB", + "AUDIO_U16MSB", + "AUDIO_S16MSB", + "AUDIO_U16", + "AUDIO_S16", + "AUDIO_U16SYS", + "AUDIO_S16SYS", + + "KMOD_NONE", + "KMOD_LSHIFT", + "KMOD_RSHIFT", + "KMOD_LCTRL", + "KMOD_RCTRL", + "KMOD_LALT", + "KMOD_RALT", + "KMOD_LMETA", + "KMOD_RMETA", + "KMOD_NUM", + "KMOD_CAPS", + "KMOD_MODE", + + "KMOD_CTRL", + "KMOD_SHIFT", + "KMOD_ALT", + "KMOD_META", ], 'SDL': [ # constants with the 'SDL' prefix in C "K_UNKNOWN", - "K_FIRST", - "K_BACKSPACE", - "K_TAB", - "K_CLEAR", - "K_RETURN", - "K_PAUSE", - "K_ESCAPE", - "K_SPACE", - "K_EXCLAIM", - "K_QUOTEDBL", - "K_HASH", - "K_DOLLAR", - "K_AMPERSAND", - "K_QUOTE", - "K_LEFTPAREN", - "K_RIGHTPAREN", - "K_ASTERISK", - "K_PLUS", - "K_COMMA", - "K_MINUS", - "K_PERIOD", - "K_SLASH", - "K_0", - "K_1", - "K_2", - "K_3", - "K_4", - "K_5", - "K_6", - "K_7", - "K_8", - "K_9", - "K_COLON", - "K_SEMICOLON", - "K_LESS", - "K_EQUALS", - "K_GREATER", - "K_QUESTION", - "K_AT", - "K_LEFTBRACKET", - "K_BACKSLASH", - "K_RIGHTBRACKET", - "K_CARET", - "K_UNDERSCORE", - "K_BACKQUOTE", - "K_a", - "K_b", - "K_c", - "K_d", - "K_e", - "K_f", - "K_g", - "K_h", - "K_i", - "K_j", - "K_k", - "K_l", - "K_m", - "K_n", - "K_o", - "K_p", - "K_q", - "K_r", - "K_s", - "K_t", - "K_u", - "K_v", - "K_w", - "K_x", - "K_y", - "K_z", - "K_DELETE", - - "K_KP0", - "K_KP1", - "K_KP2", - "K_KP3", - "K_KP4", - "K_KP5", - "K_KP6", - "K_KP7", - "K_KP8", - "K_KP9", - "K_KP_PERIOD", - "K_KP_DIVIDE", - "K_KP_MULTIPLY", - "K_KP_MINUS", - "K_KP_PLUS", - "K_KP_ENTER", - "K_KP_EQUALS", - "K_UP", - "K_DOWN", - "K_RIGHT", - "K_LEFT", - "K_INSERT", - "K_HOME", - "K_END", - "K_PAGEUP", - "K_PAGEDOWN", - "K_F1", - "K_F2", - "K_F3", - "K_F4", - "K_F5", - "K_F6", - "K_F7", - "K_F8", - "K_F9", - "K_F10", - "K_F11", - "K_F12", - "K_F13", - "K_F14", - "K_F15", - - "K_NUMLOCK", - "K_CAPSLOCK", - "K_SCROLLOCK", - "K_RSHIFT", - "K_LSHIFT", - "K_RCTRL", - "K_LCTRL", - "K_RALT", - "K_LALT", - "K_RMETA", - "K_LMETA", - "K_LSUPER", - "K_RSUPER", - "K_MODE", - - "K_HELP", - "K_PRINT", - "K_SYSREQ", - "K_BREAK", - "K_MENU", - "K_POWER", - "K_EURO", - "K_LAST", + "K_FIRST", + "K_BACKSPACE", + "K_TAB", + "K_CLEAR", + "K_RETURN", + "K_PAUSE", + "K_ESCAPE", + "K_SPACE", + "K_EXCLAIM", + "K_QUOTEDBL", + "K_HASH", + "K_DOLLAR", + "K_AMPERSAND", + "K_QUOTE", + "K_LEFTPAREN", + "K_RIGHTPAREN", + "K_ASTERISK", + "K_PLUS", + "K_COMMA", + "K_MINUS", + "K_PERIOD", + "K_SLASH", + "K_0", + "K_1", + "K_2", + "K_3", + "K_4", + "K_5", + "K_6", + "K_7", + "K_8", + "K_9", + "K_COLON", + "K_SEMICOLON", + "K_LESS", + "K_EQUALS", + "K_GREATER", + "K_QUESTION", + "K_AT", + "K_LEFTBRACKET", + "K_BACKSLASH", + "K_RIGHTBRACKET", + "K_CARET", + "K_UNDERSCORE", + "K_BACKQUOTE", + "K_a", + "K_b", + "K_c", + "K_d", + "K_e", + "K_f", + "K_g", + "K_h", + "K_i", + "K_j", + "K_k", + "K_l", + "K_m", + "K_n", + "K_o", + "K_p", + "K_q", + "K_r", + "K_s", + "K_t", + "K_u", + "K_v", + "K_w", + "K_x", + "K_y", + "K_z", + "K_DELETE", + + "K_KP0", + "K_KP1", + "K_KP2", + "K_KP3", + "K_KP4", + "K_KP5", + "K_KP6", + "K_KP7", + "K_KP8", + "K_KP9", + "K_KP_PERIOD", + "K_KP_DIVIDE", + "K_KP_MULTIPLY", + "K_KP_MINUS", + "K_KP_PLUS", + "K_KP_ENTER", + "K_KP_EQUALS", + "K_UP", + "K_DOWN", + "K_RIGHT", + "K_LEFT", + "K_INSERT", + "K_HOME", + "K_END", + "K_PAGEUP", + "K_PAGEDOWN", + "K_F1", + "K_F2", + "K_F3", + "K_F4", + "K_F5", + "K_F6", + "K_F7", + "K_F8", + "K_F9", + "K_F10", + "K_F11", + "K_F12", + "K_F13", + "K_F14", + "K_F15", + + "K_NUMLOCK", + "K_CAPSLOCK", + "K_SCROLLOCK", + "K_RSHIFT", + "K_LSHIFT", + "K_RCTRL", + "K_LCTRL", + "K_RALT", + "K_LALT", + "K_RMETA", + "K_LMETA", + "K_LSUPER", + "K_RSUPER", + "K_MODE", + + "K_HELP", + "K_PRINT", + "K_SYSREQ", + "K_BREAK", + "K_MENU", + "K_POWER", + "K_EURO", + "K_LAST", ], } From tverwaes at codespeak.net Sun May 18 17:22:45 2008 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Sun, 18 May 2008 17:22:45 +0200 (CEST) Subject: [pypy-svn] r54893 - in pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk: . test Message-ID: <20080518152245.D33062A017B@codespeak.net> Author: tverwaes Date: Sun May 18 17:22:45 2008 New Revision: 54893 Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/error.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_wrapper.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/wrapper.py Log: (cfbolz, tverwaes) add suspend, signal, highest_priority_process and wait. Add way to signal fatal and wrapper errors with messages Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/error.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/error.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/error.py Sun May 18 17:22:45 2008 @@ -15,3 +15,10 @@ class WrappingError(PrimitiveFailedError): pass +class WrapperException(SmalltalkException): + def __init__(self, msg): + self.msg = msg + +class FatalError(SmalltalkException): + def __init__(self, msg): + self.msg = msg Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_wrapper.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_wrapper.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_wrapper.py Sun May 18 17:22:45 2008 @@ -3,6 +3,7 @@ from pypy.lang.smalltalk import model from pypy.lang.smalltalk import objtable, utility from pypy.lang.smalltalk import interpreter +from pypy.lang.smalltalk.error import WrapperException, FatalError def test_simpleread(): w_o = model.W_PointersObject(None, 2) @@ -11,8 +12,8 @@ assert w.read(0) == "hello" w.write(1, "b") assert w.read(1) == "b" - py.test.raises(IndexError, "w.read(2)") - py.test.raises(IndexError, "w.write(2, \"test\")") + py.test.raises(WrapperException, "w.read(2)") + py.test.raises(WrapperException, "w.write(2, \"test\")") def test_accessor_generators(): w_o = model.W_PointersObject(None, 1) @@ -102,7 +103,11 @@ scheduler.write(0, priority_list.w_self) return scheduler - +def new_semaphore(excess_signals=0): + w_semaphore = model.W_PointersObject(None, 3) + semaphore = wrapper.SemaphoreWrapper(w_semaphore) + semaphore.store_excess_signals(utility.wrap_int(excess_signals)) + return semaphore class TestScheduler(object): def setup_method(self, meth): @@ -120,12 +125,9 @@ assert process_list.first_link() is process_list.last_link() assert process_list.first_link() is process.w_self - def old_new_process_consistency(self, process, old_process, interp, + def new_process_consistency(self, process, old_process, interp, old_active_context, new_active_context): scheduler = wrapper.scheduler() - assert old_process.suspended_context() is old_active_context - priority_list = scheduler.get_process_list(old_process.priority()) - assert priority_list.first_link() is old_process.w_self assert interp.w_active_context() is new_active_context assert scheduler.active_process() is process.w_self priority_list = wrapper.scheduler().get_process_list(process.priority()) @@ -134,35 +136,64 @@ # The caller of activate is responsible assert priority_list.first_link() is process.w_self - def test_activate(self): + def old_process_consistency(self, old_process, old_process_context): + assert old_process.suspended_context() is old_process_context + priority_list = wrapper.scheduler().get_process_list(old_process.priority()) + assert priority_list.first_link() is old_process.w_self + + def make_processes(self, sleepingpriority, runningpriority, + sleepingcontext, runningcontext): interp = interpreter.Interpreter() scheduler = wrapper.scheduler() - process = new_process(priority=2, w_suspended_context=objtable.w_false) - process.put_to_sleep() - old_process = new_process(priority=3) - scheduler.store_active_process(old_process.w_self) - interp.store_w_active_context(objtable.w_true) - process.activate(interp) + sleeping = new_process(priority=sleepingpriority, + w_suspended_context=sleepingcontext) + sleeping.put_to_sleep() + running = new_process(priority=runningpriority) + scheduler.store_active_process(running.w_self) + interp.store_w_active_context(runningcontext) + + return interp, sleeping, running + - self.old_new_process_consistency(process, old_process, interp, + def test_activate(self): + interp, process, old_process = self.make_processes(4, 2, objtable.w_false, objtable.w_true) + process.activate(interp) + self.new_process_consistency(process, old_process, interp, objtable.w_true, objtable.w_false) def test_resume(self): - interp = interpreter.Interpreter() - scheduler = wrapper.scheduler() - process = new_process(priority=4, w_suspended_context=objtable.w_false) - process.put_to_sleep() - old_process = new_process(priority=2) - scheduler.store_active_process(old_process.w_self) - interp.store_w_active_context(objtable.w_true) - + interp, process, old_process = self.make_processes(4, 2, objtable.w_false, objtable.w_true) process.resume(interp) - self.old_new_process_consistency(process, old_process, interp, + self.new_process_consistency(process, old_process, interp, objtable.w_true, objtable.w_false) + self.old_process_consistency(old_process, objtable.w_true) # Does not reactivate old_process because lower priority old_process.resume(interp) - self.old_new_process_consistency(process, old_process, interp, + self.new_process_consistency(process, old_process, interp, objtable.w_true, objtable.w_false) + self.old_process_consistency(old_process, objtable.w_true) - + def test_semaphore_excess_signal(self): + semaphore = new_semaphore() + + semaphore.signal(None) + assert utility.unwrap_int(semaphore.excess_signals()) == 1 + + def test_highest_priority(self): + py.test.raises(FatalError, wrapper.scheduler().highest_priority_process) + interp, process, old_process = self.make_processes(4, 2, objtable.w_false, objtable.w_true) + process.put_to_sleep() + old_process.put_to_sleep() + highest = wrapper.scheduler().highest_priority_process() + assert highest is process.w_self + highest = wrapper.scheduler().highest_priority_process() + assert highest is old_process.w_self + py.test.raises(FatalError, wrapper.scheduler().highest_priority_process) + + def test_semaphore_wait(self): + semaphore = new_semaphore() + interp, process, old_process = self.make_processes(4, 2, objtable.w_false, objtable.w_true) + semaphore.wait(interp) + assert semaphore.first_link() is old_process.w_self + assert wrapper.scheduler().active_process() is process.w_self Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/wrapper.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/wrapper.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/wrapper.py Sun May 18 17:22:45 2008 @@ -1,24 +1,24 @@ from pypy.lang.smalltalk import model -from pypy.lang.smalltalk import utility +from pypy.lang.smalltalk import utility, objtable +from pypy.lang.smalltalk.error import FatalError, WrapperException class Wrapper(object): def __init__(self, w_self): - assert isinstance(w_self, model.W_PointersObject) + if not isinstance(w_self, model.W_PointersObject): + raise WrapperException("Unexpected instance given to wrapper") self.w_self = w_self def read(self, index0): try: return self.w_self._vars[index0] except IndexError: - # XXX nicer errormessage - raise + raise WrapperException("Unexpected instance layout. Too small") def write(self, index0, w_new): try: self.w_self._vars[index0] = w_new except IndexError: - # XXX nicer errormessage - raise + raise WrapperException("Unexpected instance layout. Too small") def make_getter(index0): def getter(self): @@ -53,24 +53,32 @@ def activate(self, interp): from pypy.lang.smalltalk import objtable sched = scheduler() - w_old_process = sched.active_process() sched.store_active_process(self.w_self) - old_process = ProcessWrapper(w_old_process) - old_process.store_suspended_context(interp.w_active_context()) - old_process.put_to_sleep() interp.store_w_active_context(self.suspended_context()) self.store_suspended_context(objtable.w_nil) + def deactivate(self, interp): + self.put_to_sleep() + self.store_suspended_context(interp.w_active_context()) + def resume(self, interp): sched = scheduler() active_process = ProcessWrapper(sched.active_process()) active_priority = active_process.priority() priority = self.priority() if priority > active_priority: + active_process.deactivate(interp) self.activate(interp) else: self.put_to_sleep() + def is_active_process(self): + return self.w_self is scheduler().active_process() + + def suspend(self, interp): + assert self.is_active_process() + assert self.my_list() is objtable.w_nil + ProcessWrapper(scheduler().highest_priority_process()).activate(interp) class LinkedListWrapper(Wrapper): first_link, store_first_link = make_getter_setter(0) @@ -117,6 +125,18 @@ lists = self.priority_list() return ProcessListWrapper(Wrapper(lists).read(priority)) + def highest_priority_process(self): + w_lists = self.priority_list() + # Asserts as W_PointersObject + lists = Wrapper(w_lists) + + for i in range(len(w_lists._vars) -1, -1, -1): + process_list = ProcessListWrapper(lists.read(i)) + if not process_list.is_empty_list(): + return process_list.remove_first_link_of_list() + + raise FatalError("Scheduler could not find a runnable process") + def scheduler(): from pypy.lang.smalltalk import objtable w_association = objtable.objtable["w_schedulerassociationpointer"] @@ -127,7 +147,7 @@ class SemaphoreWrapper(LinkedListWrapper): - excess_signals, store_excess_signals = make_getter_setter(0) + excess_signals, store_excess_signals = make_getter_setter(2) def signal(self, interp): if self.is_empty_list(): @@ -135,13 +155,14 @@ w_value = utility.wrap_int(utility.unwrap_int(w_value) + 1) self.store_excess_signals(w_value) else: - self.resume(self.remove_first_link_of_list(), interp) + self.remove_first_link_of_list().resume(interp) - def wait(self, w_process, interp): + def wait(self, interp): excess = utility.unwrap_int(self.excess_signals()) + w_process = scheduler().active_process() if excess > 0: w_excess = utility.wrap_int(excess - 1) self.store_excess_signals(w_excess) else: self.add_last_link(w_process) - ProcessWrapper(w_process).put_to_sleep() + ProcessWrapper(w_process).suspend(interp) From tverwaes at codespeak.net Sun May 18 17:29:38 2008 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Sun, 18 May 2008 17:29:38 +0200 (CEST) Subject: [pypy-svn] r54894 - in pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk: . test Message-ID: <20080518152938.8032C2A018A@codespeak.net> Author: tverwaes Date: Sun May 18 17:29:35 2008 New Revision: 54894 Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_wrapper.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/wrapper.py Log: (cfbolz, tverwaes) test for signal, wait, wait Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_wrapper.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_wrapper.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_wrapper.py Sun May 18 17:29:35 2008 @@ -197,3 +197,16 @@ semaphore.wait(interp) assert semaphore.first_link() is old_process.w_self assert wrapper.scheduler().active_process() is process.w_self + + def test_semaphore_signal_wait(self): + semaphore = new_semaphore() + semaphore.signal(None) + interp, process, old_process = self.make_processes(4, 2, objtable.w_false, objtable.w_true) + semaphore.wait(interp) + assert semaphore.is_empty_list() + assert wrapper.scheduler().active_process() is old_process.w_self + semaphore.wait(interp) + assert semaphore.first_link() is old_process.w_self + assert wrapper.scheduler().active_process() is process.w_self + + py.test.raises(FatalError, semaphore.wait, interp) Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/wrapper.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/wrapper.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/wrapper.py Sun May 18 17:29:35 2008 @@ -56,6 +56,7 @@ sched.store_active_process(self.w_self) interp.store_w_active_context(self.suspended_context()) self.store_suspended_context(objtable.w_nil) + self.store_my_list(objtable.w_nil) def deactivate(self, interp): self.put_to_sleep() From fijal at codespeak.net Sun May 18 17:34:32 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 18 May 2008 17:34:32 +0200 (CEST) Subject: [pypy-svn] r54895 - in pypy/branch/hybrid-io/pypy/rpython/memory: gc gctransform test Message-ID: <20080518153432.19E832A017B@codespeak.net> Author: fijal Date: Sun May 18 17:34:31 2008 New Revision: 54895 Modified: pypy/branch/hybrid-io/pypy/rpython/memory/gc/hybrid.py pypy/branch/hybrid-io/pypy/rpython/memory/gctransform/framework.py pypy/branch/hybrid-io/pypy/rpython/memory/gctransform/transform.py pypy/branch/hybrid-io/pypy/rpython/memory/test/test_transformed_gc.py Log: Implement correct realloc for hybrid gc (still can be improved performance wise) Modified: pypy/branch/hybrid-io/pypy/rpython/memory/gc/hybrid.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/memory/gc/hybrid.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/memory/gc/hybrid.py Sun May 18 17:34:31 2008 @@ -30,6 +30,7 @@ # Object lists: # * gen2_rawmalloced_objects # * gen3_rawmalloced_objects +# * gen_resizable_objects # * old_objects_pointing_to_young: gen2or3 objs that point to gen1 objs # * last_generation_root_objects: gen3 objs that point to gen1or2 objs # @@ -47,6 +48,8 @@ # but initially of generation 2. Old objects from the semispaces are # moved to external objects directly as generation 3. +# gen_resizable objects is for objects that are resizable + # The "age" of an object is the number of times it survived a full # collections, without counting the step that moved it out of the nursery. # When a semispace-based object would grow older than MAX_SEMISPACE_AGE, @@ -118,6 +121,7 @@ def setup(self): self.gen2_rawmalloced_objects = self.AddressStack() self.gen3_rawmalloced_objects = self.AddressStack() + self.gen_resizable_objects = self.AddressStack() GenerationGC.setup(self) def set_max_heap_size(self, size): @@ -170,7 +174,8 @@ llmemory.GCREF) return self.malloc_varsize_slowpath(typeid, length) - def malloc_varsize_slowpath(self, typeid, length, force_old=False): + def malloc_varsize_slowpath(self, typeid, length, force_old=False, + resizable=False): # For objects that are too large, or when the nursery is exhausted. # In order to keep malloc_varsize_clear() as compact as possible, # we recompute what we need in this slow path instead of passing @@ -189,7 +194,7 @@ else: nonlarge_max = self.nonlarge_max if force_old or raw_malloc_usage(totalsize) > nonlarge_max: - result = self.malloc_varsize_marknsweep(totalsize) + result = self.malloc_varsize_marknsweep(totalsize, resizable) flags = self.GCFLAGS_FOR_NEW_EXTERNAL_OBJECTS | GCFLAG_UNVISITED else: result = self.malloc_varsize_collecting_nursery(totalsize) @@ -199,11 +204,14 @@ return llmemory.cast_adr_to_ptr(result+size_gc_header, llmemory.GCREF) malloc_varsize_slowpath._dont_inline_ = True - malloc_varsize_slowpath._annspecialcase_ = 'specialize:arg(3)' + malloc_varsize_slowpath._annspecialcase_ = 'specialize:arg(3, 4)' def malloc_varsize_nonmovable(self, typeid, length): return self.malloc_varsize_slowpath(typeid, length, True) + def malloc_varsize_resizable(self, typeid, length): + return self.malloc_varsize_slowpath(typeid, length, True, True) + def malloc_nonmovable(self, typeid, length, zero): # helper for testing, same as GCBase.malloc if self.is_varsize(typeid): @@ -220,6 +228,7 @@ oldsize = (addr + lengthofs).signed[0] old_tot_size = size_gc_header + const_size + oldsize * itemsize source_addr = addr - size_gc_header + self._remove_addr_from_resizable_objects(addr) if grow: result = llop.raw_realloc_grow(llmemory.Address, source_addr, old_tot_size, tot_size) @@ -228,13 +237,22 @@ old_tot_size, tot_size) if not result: raise MemoryError() - if result != addr: - flags = self.GCFLAGS_FOR_NEW_EXTERNAL_OBJECTS | GCFLAG_UNVISITED - self.gen2_rawmalloced_objects.append(result) - self.init_gc_object(result, tid, flags) + if grow: + self.gen_resizable_objects.append(result + size_gc_header) + else: + self.gen2_rawmalloced_objects.append(result + size_gc_header) (result + size_gc_header + lengthofs).signed[0] = newsize return llmemory.cast_adr_to_ptr(result + size_gc_header, llmemory.GCREF) + def _remove_addr_from_resizable_objects(self, addr): + objects = self.gen_resizable_objects + newstack = self.AddressStack() + while objects.non_empty(): + obj = objects.pop() + if obj != addr: + newstack.append(obj) + self.gen_resizable_objects = newstack + def can_move(self, addr): tid = self.header(addr).tid return not (tid & GCFLAG_EXTERNAL) @@ -248,7 +266,7 @@ totalsize) return result - def malloc_varsize_marknsweep(self, totalsize): + def malloc_varsize_marknsweep(self, totalsize, resizable=False): # In order to free the large objects from time to time, we # arbitrarily force a full collect() if none occurs when we have # allocated 'self.space_size' bytes of large objects. @@ -271,8 +289,12 @@ # need to follow suit. llmemory.raw_memclear(result, totalsize) size_gc_header = self.gcheaderbuilder.size_gc_header - self.gen2_rawmalloced_objects.append(result + size_gc_header) + if resizable: + self.gen_resizable_objects.append(result + size_gc_header) + else: + self.gen2_rawmalloced_objects.append(result + size_gc_header) return result + malloc_varsize_marknsweep._annspecialcase_ = 'specialize:arg(2)' def allocate_external_object(self, totalsize): # XXX maybe we should use arena_malloc() above a certain size? Modified: pypy/branch/hybrid-io/pypy/rpython/memory/gctransform/framework.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/memory/gctransform/framework.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/memory/gctransform/framework.py Sun May 18 17:34:31 2008 @@ -284,6 +284,17 @@ else: self.malloc_varsize_nonmovable_ptr = None + if getattr(GCClass, 'malloc_varsize_resizable', False): + malloc_resizable = func_with_new_name( + GCClass.malloc_varsize_resizable.im_func, + "malloc_varsize_resizable") + self.malloc_varsize_resizable_ptr = getfn( + malloc_resizable, + [s_gc, annmodel.SomeInteger(nonneg=True), + annmodel.SomeInteger(nonneg=True)], s_gcref) + else: + self.malloc_varsize_resizable_ptr = None + if getattr(GCClass, 'realloc', False): self.realloc_ptr = getfn( GCClass.realloc.im_func, @@ -475,7 +486,12 @@ v_length = op.args[-1] c_ofstolength = rmodel.inputconst(lltype.Signed, info.ofstolength) c_varitemsize = rmodel.inputconst(lltype.Signed, info.varitemsize) - if flags.get('nonmovable') and self.malloc_varsize_nonmovable_ptr: + if flags.get('resizable') and self.malloc_varsize_resizable_ptr: + assert c_can_collect.value + assert not c_has_finalizer.value + malloc_ptr = self.malloc_varsize_resizable_ptr + args = [self.c_const_gc, c_type_id, v_length] + elif flags.get('nonmovable') and self.malloc_varsize_nonmovable_ptr: # we don't have tests for such cases, let's fail # explicitely assert c_can_collect.value Modified: pypy/branch/hybrid-io/pypy/rpython/memory/gctransform/transform.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/memory/gctransform/transform.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/memory/gctransform/transform.py Sun May 18 17:34:31 2008 @@ -540,6 +540,7 @@ flags = hop.spaceop.args[1].value flags['varsize'] = True flags['nonmovable'] = True + flags['resizable'] = True flavor = flags['flavor'] assert flavor != 'cpy', "cannot malloc CPython objects directly" meth = getattr(self, 'gct_fv_%s_malloc_varsize' % flavor, None) Modified: pypy/branch/hybrid-io/pypy/rpython/memory/test/test_transformed_gc.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/memory/test/test_transformed_gc.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/memory/test/test_transformed_gc.py Sun May 18 17:34:31 2008 @@ -510,7 +510,6 @@ def test_string_builder_over_allocation(self): import gc - py.test.skip("Problematic test") def fn(): s = StringBuilder(4) s.append("abcd") @@ -519,7 +518,9 @@ s.append_multiple_char('y', 1000) gc.collect() s.append_multiple_char('y', 1000) - return s.build()[1000] + res = s.build()[1000] + gc.collect() + return res fn = self.runner(fn) res = fn([]) assert res == 'y' From tverwaes at codespeak.net Sun May 18 17:40:29 2008 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Sun, 18 May 2008 17:40:29 +0200 (CEST) Subject: [pypy-svn] r54896 - in pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk: . test Message-ID: <20080518154029.023532A0181@codespeak.net> Author: tverwaes Date: Sun May 18 17:40:29 2008 New Revision: 54896 Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_wrapper.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/wrapper.py Log: (cfbolz, tverwaes) implementing the wait, signal test + bugfix Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_wrapper.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_wrapper.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_wrapper.py Sun May 18 17:40:29 2008 @@ -210,3 +210,25 @@ assert wrapper.scheduler().active_process() is process.w_self py.test.raises(FatalError, semaphore.wait, interp) + + def test_semaphore_wait_signal(self): + semaphore = new_semaphore() + interp, process, old_process = self.make_processes(4, 2, objtable.w_false, objtable.w_true) + + semaphore.wait(interp) + assert wrapper.scheduler().active_process() is process.w_self + semaphore.signal(interp) + assert wrapper.scheduler().active_process() is process.w_self + process_list = wrapper.scheduler().get_process_list(old_process.priority()) + assert process_list.remove_first_link_of_list() is old_process.w_self + + process.write(2, utility.wrap_int(1)) + old_process.resume(interp) + assert wrapper.scheduler().active_process() is old_process.w_self + semaphore.wait(interp) + assert wrapper.scheduler().active_process() is process.w_self + semaphore.signal(interp) + assert wrapper.scheduler().active_process() is old_process.w_self + + process_list = wrapper.scheduler().get_process_list(process.priority()) + assert process_list.first_link() is process.w_self Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/wrapper.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/wrapper.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/wrapper.py Sun May 18 17:40:29 2008 @@ -156,7 +156,7 @@ w_value = utility.wrap_int(utility.unwrap_int(w_value) + 1) self.store_excess_signals(w_value) else: - self.remove_first_link_of_list().resume(interp) + ProcessWrapper(self.remove_first_link_of_list()).resume(interp) def wait(self, interp): excess = utility.unwrap_int(self.excess_signals()) From tverwaes at codespeak.net Sun May 18 18:11:28 2008 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Sun, 18 May 2008 18:11:28 +0200 (CEST) Subject: [pypy-svn] r54897 - in pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk: . test Message-ID: <20080518161128.F17092A805E@codespeak.net> Author: tverwaes Date: Sun May 18 18:11:26 2008 New Revision: 54897 Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_wrapper.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/wrapper.py Log: (cfbolz, tverwaes) fixing suspend so it can suspend sleeping processes Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_wrapper.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_wrapper.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_wrapper.py Sun May 18 18:11:26 2008 @@ -55,6 +55,13 @@ linkedlist.add_last_link(w_last) assert linkedlist.first_link() is w_first assert linkedlist.last_link() is w_last + py.test.raises(WrapperException, linkedlist.remove, objtable.w_nil) + linkedlist.remove(w_first) + assert linkedlist.first_link() is w_last + linkedlist.store_first_link(w_first) + wrapper.LinkWrapper(w_first).store_next_link(w_last) + linkedlist.remove(w_last) + assert linkedlist.last_link() is w_first def new_process(w_next=objtable.w_nil, w_my_list=objtable.w_nil, @@ -109,6 +116,7 @@ semaphore.store_excess_signals(utility.wrap_int(excess_signals)) return semaphore + class TestScheduler(object): def setup_method(self, meth): self.old_scheduler = wrapper.scheduler @@ -118,13 +126,30 @@ def teardown_method(self, meth): wrapper.scheduler = self.old_scheduler - def test_suspend(self): + def test_put_to_sleep(self): process = new_process(priority=2) process.put_to_sleep() process_list = wrapper.scheduler().get_process_list(2) assert process_list.first_link() is process_list.last_link() assert process_list.first_link() is process.w_self + def test_suspend_asleep(self): + interp, process, old_process = self.make_processes(4, 2, objtable.w_false, objtable.w_true) + process.suspend(interp) + process_list = wrapper.scheduler().get_process_list(process.priority()) + assert process_list.first_link() is process_list.last_link() + assert process_list.first_link() is objtable.w_nil + assert process.my_list() is objtable.w_nil + + def test_suspend_active(self): + interp, process, old_process = self.make_processes(4, 2, objtable.w_false, objtable.w_true) + old_process.suspend(interp) + process_list = wrapper.scheduler().get_process_list(old_process.priority()) + assert process_list.first_link() is process_list.last_link() + assert process_list.first_link() is objtable.w_nil + assert old_process.my_list() is objtable.w_nil + assert wrapper.scheduler().active_process() is process.w_self + def new_process_consistency(self, process, old_process, interp, old_active_context, new_active_context): scheduler = wrapper.scheduler() Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/wrapper.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/wrapper.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/wrapper.py Sun May 18 18:11:26 2008 @@ -77,9 +77,13 @@ return self.w_self is scheduler().active_process() def suspend(self, interp): - assert self.is_active_process() - assert self.my_list() is objtable.w_nil - ProcessWrapper(scheduler().highest_priority_process()).activate(interp) + if self.is_active_process(): + assert self.my_list() is objtable.w_nil + ProcessWrapper(scheduler().highest_priority_process()).activate(interp) + else: + process_list = ProcessListWrapper(self.my_list()) + process_list.remove(self.w_self) + self.store_my_list(objtable.w_nil) class LinkedListWrapper(Wrapper): first_link, store_first_link = make_getter_setter(0) @@ -109,6 +113,25 @@ LinkWrapper(w_first).store_next_link(objtable.w_nil) return w_first + def remove(self, w_link): + if self.first_link() is w_link: + self.remove_first_link_of_list() + return + else: + current = LinkWrapper(self.first_link()) + w_next = current.next_link() + while w_next is not objtable.w_nil: + if w_next is w_link: + LinkWrapper(w_link).store_next_link(objtable.w_nil) + w_tail = LinkWrapper(w_next).next_link() + current.store_next_link(w_tail) + if w_tail is objtable.w_nil: + self.store_last_link(current.w_self) + return + current = LinkWrapper(w_next) + w_next = current.next_link() + raise WrapperException("Could not find link") + class ProcessListWrapper(LinkedListWrapper): def add_process(self, w_process): self.add_last_link(w_process) From cami at codespeak.net Sun May 18 18:12:41 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Sun, 18 May 2008 18:12:41 +0200 (CEST) Subject: [pypy-svn] r54898 - in pypy/branch/gameboy-emulator/pypy/lang/gameboy: . test Message-ID: <20080518161241.089EB398009@codespeak.net> Author: cami Date: Sun May 18 18:12:40 2008 New Revision: 54898 Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cpu.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/video.py Log: updated callwrapper, so the objects themselfs are passed not the function of the callWrappers Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/cpu.py Sun May 18 18:12:40 2008 @@ -389,7 +389,7 @@ return (hi << 8) + lo def fetch_double_register(self, register): - self.double_register_inverse_call(CPUFetchCaller(self).get, register) + self.double_register_inverse_call(CPUFetchCaller(self), register) def push(self, data, use_cycles=True): # Stack, 2 cycles @@ -410,11 +410,11 @@ def pop_double_register(self, register): # 3 cycles - self.double_register_inverse_call(CPUPopCaller(self).get, register) + self.double_register_inverse_call(CPUPopCaller(self), register) - def double_register_inverse_call(self, getter, register): - b = getter() # 1 cycle - a = getter() # 1 cycle + def double_register_inverse_call(self, getCaller, register): + b = getCaller.get() # 1 cycle + a = getCaller.get() # 1 cycle register.set_hi_lo(a, b) # 2 cycles self.cycles += 1 @@ -426,24 +426,24 @@ if use_cycles: self.cycles += 1 - def ld(self, getter, setter): + def ld(self, getCaller, setCaller): # 1 cycle - setter(getter()) # 1 cycle + setCaller.set(getCaller.get()) # 1 cycle def load_fetch_register(self, register): - self.ld(CPUFetchCaller(self).get, RegisterSetCaller(register).set) + self.ld(CPUFetchCaller(self), RegisterCallWrapper(register)) def store_hl_in_pc(self): # LD PC,HL, 1 cycle - self.ld(DoubleRegisterGetCaller(self.hl).get, \ - DoubleRegisterSetCaller(self.pc).set) + self.ld(DoubleRegisterCallWrapper(self.hl), \ + DoubleRegisterCallWrapper(self.pc)) - def fetch_load(self, getter, setter): - self.ld(CPUFetchCaller(self).get, setter) + def fetch_load(self, getCaller, setCaller): + self.ld(CPUFetchCaller(self), setCaller) - def add_a(self, getter, setter=None): + def add_a(self, getCaller, setCaller=None): # ALU, 1 cycle - added = (self.a.get() + getter()) & 0xFF + added = (self.a.get() + getCaller.get()) & 0xFF self.f.z_flag_compare(added, reset=True) self.f.h_flag_compare(added, self.a.get()) self.f.c_flag_compare(added, self.a.get()) @@ -459,17 +459,17 @@ self.hl.set(added) self.cycles -= 1 - def add_with_carry(self, getter, setter=None): + def add_with_carry(self, getCaller, setCaller=None): # 1 cycle - data = getter() + data = getCaller.get() s = self.a.get() + data if self.f.c_flag: s +=1 self.carry_flag_finish(s,data) - def subtract_with_carry(self, getter, setter=None): + def subtract_with_carry(self, getCaller, setCaller=None): # 1 cycle - data = getter() + data = getCaller.get() s = self.a.get() - data if self.f.c_flag: s -= 1 @@ -486,10 +486,10 @@ self.f.z_flag_compare(s) self.a.set(s) # 1 cycle - def subtract_a(self, getter, setter=None): + def subtract_a(self, getCaller, setCaller=None): # 1 cycle - self.compare_a(getter) # 1 cycle - self.a.sub(getter(use_cycles=False), False) + self.compare_a(getCaller) # 1 cycle + self.a.sub(getCaller.get(use_cycles=False), False) def fetch_subtract_a(self): data = self.fetch() @@ -497,9 +497,9 @@ self.compare_a_simple(data) # 1 cycle self.a.sub(data, False) - def compare_a(self, getter, setter=None): + def compare_a(self, getCaller, setCaller=None): # 1 cycle - self.compare_a_simple(int(self.a.get() - getter())) + self.compare_a_simple(int(self.a.get() - getCaller.get())) def compare_a_simple(self, s): s = s & 0xFF @@ -514,19 +514,19 @@ self.f.c_flag = True self.f.h_flag_compare(self.a.get(), data) - def AND(self, getter, setter=None): + def AND(self, getCaller, setCaller=None): # 1 cycle - self.a.set(self.a.get() & getter()) # 1 cycle + self.a.set(self.a.get() & getCaller.get()) # 1 cycle self.f.z_flag_compare(self.a.get(), reset=True) - def XOR(self, getter, setter=None): + def XOR(self, getCaller, setCaller=None): # 1 cycle - self.a.set( self.a.get() ^ getter()) # 1 cycle + self.a.set( self.a.get() ^ getCaller.get()) # 1 cycle self.f.z_flag_compare(self.a.get(), reset=True) - def OR(self, getter, setter=None): + def OR(self, getCaller, setCaller=None): # 1 cycle - self.a.set(self.a.get() | getter()) # 1 cycle + self.a.set(self.a.get() | getCaller.get()) # 1 cycle self.f.z_flag_compare(self.a.get(), reset=True) def inc_double_register(self, doubleRegister): @@ -535,117 +535,117 @@ def dec_double_register(self, doubleRegister): doubleRegister.dec() - def inc(self, getter, setter): + def inc(self, getCaller, setCaller): # 1 cycle - data = (getter() + 1) & 0xFF - self.dec_inc_flag_finish(data, setter, 0x00) + data = (getCaller.get() + 1) & 0xFF + self.dec_inc_flag_finish(data, setCaller, 0x00) - def dec(self, getter, setter): + def dec(self, getCaller, setCaller): # 1 cycle - data = (getter() - 1) & 0xFF - self.dec_inc_flag_finish(data, setter, 0x0F) + data = (getCaller.get() - 1) & 0xFF + self.dec_inc_flag_finish(data, setCaller, 0x0F) self.f.n_flag = True - def dec_inc_flag_finish(self, data, setter, compare): + def dec_inc_flag_finish(self, data, setCaller, compare): self.f.partial_reset(keep_c=True) self.f.z_flag_compare(data) if (data & 0x0F) == compare: self.f.h_flag = True - setter(data) # 1 cycle + setCaller.set(data) # 1 cycle - def rotate_left_circular(self, getter, setter): + def rotate_left_circular(self, getCaller, setCaller): # RLC 1 cycle - data = getter() + data = getCaller.get() s = (data << 1) + (data >> 7) - self.flags_and_setter_finish(s, setter, 0x80) + self.flags_and_setter_finish(s, setCaller, 0x80) #self.cycles -= 1 def rotate_left_circular_a(self): # RLCA rotate_left_circular_a 1 cycle - self.rotate_left_circular(RegisterGetCaller(self.a).get, \ - RegisterSetCaller(self.a).set) + self.rotate_left_circular(RegisterCallWrapper(self.a), \ + RegisterCallWrapper(self.a)) - def rotate_left(self, getter, setter): + def rotate_left(self, getCaller, setCaller): # 1 cycle - s = (getter() << 1) & 0xFF + s = (getCaller.get() << 1) & 0xFF if self.f.c_flag: s += 0x01 - self.flags_and_setter_finish(s, setter, 0x80) # 1 cycle + self.flags_and_setter_finish(s, setCaller, 0x80) # 1 cycle def rotate_left_a(self): # RLA 1 cycle - self.rotate_left(RegisterGetCaller(self.a).get, \ - RegisterSetCaller(self.a).set) + self.rotate_left(RegisterCallWrapper(self.a), \ + RegisterCallWrapper(self.a)) - def rotate_right_circular(self, getter, setter): - data = getter() + def rotate_right_circular(self, getCaller, setCaller): + data = getCaller.get() # RRC 1 cycle s = (data >> 1) + ((data & 0x01) << 7) - self.flags_and_setter_finish(s, setter) # 1 cycle + self.flags_and_setter_finish(s, setCaller) # 1 cycle def rotate_right_circular_a(self): # RRCA 1 cycle - self.rotate_right_circular(RegisterGetCaller(self.a).get, \ - RegisterSetCaller(self.a).set) + self.rotate_right_circular(RegisterCallWrapper(self.a), \ + RegisterCallWrapper(self.a)) - def rotate_right(self, getter, setter): + def rotate_right(self, getCaller, setCaller): # 1 cycle - s = (getter() >> 1) + s = (getCaller.get() >> 1) if self.f.c_flag: s += 0x08 - self.flags_and_setter_finish(s, setter) # 1 cycle + self.flags_and_setter_finish(s, setCaller) # 1 cycle def rotate_right_a(self): # RRA 1 cycle - self.rotate_right(RegisterGetCaller(self.a).get, \ - RegisterSetCaller(self.a).set) + self.rotate_right(RegisterCallWrapper(self.a), \ + RegisterCallWrapper(self.a)) - def shift_left_arithmetic(self, getter, setter): + def shift_left_arithmetic(self, getCaller, setCaller): # 2 cycles - s = (getter() << 1) & 0xFF - self.flags_and_setter_finish(s, setter, 0x80) # 1 cycle + s = (getCaller.get() << 1) & 0xFF + self.flags_and_setter_finish(s, setCaller, 0x80) # 1 cycle - def shift_right_arithmetic(self, getter, setter): - data = getter() + def shift_right_arithmetic(self, getCaller, setCaller): + data = getCaller.get() # 1 cycle s = (data >> 1) + (data & 0x80) - self.flags_and_setter_finish(s, setter) # 1 cycle + self.flags_and_setter_finish(s, setCaller) # 1 cycle - def shift_word_right_logical(self, getter, setter): + def shift_word_right_logical(self, getCaller, setCaller): # 2 cycles - s = (getter() >> 1) - self.flags_and_setter_finish(s, setter) # 2 cycles + s = (getCaller.get() >> 1) + self.flags_and_setter_finish(s, setCaller) # 2 cycles - def flags_and_setter_finish(self, s, setter, compare_and=0x01): + def flags_and_setter_finish(self, s, setCaller, compare_and=0x01): # 2 cycles s &= 0xFF self.f.z_flag_compare(s, reset=True) self.f.c_flag_add(s, compare_and) - setter(s) # 1 cycle + setCaller.set(s) # 1 cycle - def swap(self, getter, setter): - data = getter() + def swap(self, getCaller, setCaller): + data = getCaller.get() # 1 cycle s = ((data << 4) + (data >> 4)) & 0xFF self.f.z_flag_compare(s, reset=True) - setter(s) + setCaller.set(s) - def test_bit(self, getter, setter, n): + def test_bit(self, getCaller, setCaller, n): # 2 cycles self.f.partial_reset(keep_c=True) self.f.h_flag = True self.f.z_flag = False - if (getter() & (1 << n)) == 0: + if (getCaller.get() & (1 << n)) == 0: self.f.z_flag = True self.cycles -= 1 - def set_bit(self, getter, setter, n): + def set_bit(self, getCaller, setCaller, n): # 1 cycle - setter(getter() | (1 << n)) # 1 cycle + setCaller.set(getCaller.get() | (1 << n)) # 1 cycle - def reset_bit(self, getter, setter, n): + def reset_bit(self, getCaller, setCaller, n): # 1 cycle - setter(getter() & (~(1 << n))) # 1 cycle + setCaller.set(getCaller.get() & (~(1 << n))) # 1 cycle def store_fetched_memory_in_a(self): # LD A,(nnnn), 4 cycles @@ -889,39 +889,31 @@ class CallWrapper(object): def get(self, use_cycles=True): + raise Exception("called CalLWrapper.get") return 0 def set(self, value, use_cycles=True): + raise Exception("called CalLWrapper.set") pass -class RegisterGetCaller(CallWrapper): +class RegisterCallWrapper(CallWrapper): def __init__(self, register): self.register = register def get(self, use_cycles=True): return self.register.get(use_cycles) + + def set(self, value, use_cycles=True): + return self.register.set(value, use_cycles) -class DoubleRegisterGetCaller(RegisterGetCaller): +class DoubleRegisterCallWrapper(CallWrapper): def __init__(self, register): self.register = register def get(self, use_cycles=True): return self.register.get(use_cycles) - -class RegisterSetCaller(CallWrapper): - def __init__(self, register): - self.register = register - - def set(self, value, use_cycles=True): - return self.register.set(value, use_cycles) - - -class DoubleRegisterSetCaller(CallWrapper): - def __init__(self, register): - self.register = register - def set(self, value, use_cycles=True): return self.register.set(value, use_cycles) @@ -981,11 +973,11 @@ def group_lambda(function, register_getter, value=None): if value is None: - return lambda s: function(s, RegisterGetCaller(register_getter(s)).get, \ - RegisterSetCaller(register_getter(s)).set) + return lambda s: function(s, RegisterCallWrapper(register_getter(s)), \ + RegisterCallWrapper(register_getter(s))) else: - return lambda s: function(s, RegisterGetCaller(register_getter(s)).get, \ - RegisterSetCaller(register_getter(s)).set, value) + return lambda s: function(s, RegisterCallWrapper(register_getter(s)), \ + RegisterCallWrapper(register_getter(s)), value) def create_load_group_op_codes(): opCodes = [] @@ -998,8 +990,8 @@ return opCodes def load_group_lambda(store_register, load_register): - return lambda s: CPU.ld(s, RegisterGetCaller(load_register(s)).get, \ - RegisterSetCaller(store_register(s)).set) + return lambda s: CPU.ld(s, RegisterCallWrapper(load_register(s)), \ + RegisterCallWrapper(store_register(s))) def create_register_op_codes(table): @@ -1074,14 +1066,14 @@ (0xF8, CPU.store_fetch_added_sp_in_hl), (0xCB, CPU.fetch_execute), (0xCD, CPU.unconditional_call), - (0xC6, lambda s: CPU.add_a(s, CPUFetchCaller(s).get)), - (0xCE, lambda s: CPU.add_with_carry(s, CPUFetchCaller(s).get)), + (0xC6, lambda s: CPU.add_a(s, CPUFetchCaller(s))), + (0xCE, lambda s: CPU.add_with_carry(s, CPUFetchCaller(s))), (0xD6, CPU.fetch_subtract_a), - (0xDE, lambda s: CPU.subtract_with_carry(s, CPUFetchCaller(s).get)), - (0xE6, lambda s: CPU.AND(s, CPUFetchCaller(s).get)), - (0xEE, lambda s: CPU.XOR(s, CPUFetchCaller(s).get)), - (0xF6, lambda s: CPU.OR(s, CPUFetchCaller(s).get)), - (0xFE, lambda s: CPU.compare_a(s, CPUFetchCaller(s).get)), + (0xDE, lambda s: CPU.subtract_with_carry(s, CPUFetchCaller(s))), + (0xE6, lambda s: CPU.AND(s, CPUFetchCaller(s))), + (0xEE, lambda s: CPU.XOR(s, CPUFetchCaller(s))), + (0xF6, lambda s: CPU.OR(s, CPUFetchCaller(s))), + (0xFE, lambda s: CPU.compare_a(s, CPUFetchCaller(s))), (0xC7, lambda s: CPU.restart(s, 0x00)), (0xCF, lambda s: CPU.restart(s, 0x08)), (0xD7, lambda s: CPU.restart(s, 0x10)), Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cpu.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cpu.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cpu.py Sun May 18 18:12:40 2008 @@ -495,15 +495,15 @@ a = cpu.a a.set(0xFF) cpu.f.c_flag = True - cpu.inc(a.get, a.set) + cpu.inc(RegisterCallWrapper(a), RegisterCallWrapper(a)) assert_default_flags(cpu, z_flag=True, h_flag=True, c_flag=True) a.set(0x01) - cpu.inc(a.get, a.set) + cpu.inc(RegisterCallWrapper(a), RegisterCallWrapper(a)) assert_default_flags(cpu, z_flag=False, h_flag=False, c_flag=True) a.set(0x0F) - cpu.inc(a.get, a.set) + cpu.inc(RegisterCallWrapper(a), RegisterCallWrapper(a)) assert_default_flags(cpu, z_flag=False, h_flag=True, c_flag=True) # inc_B C D E H L A @@ -541,11 +541,11 @@ a = cpu.a a.set(1) cpu.f.c_flag = True - cpu.dec(a.get, a.set) + cpu.dec(RegisterCallWrapper(a), RegisterCallWrapper(a)) assert_default_flags(cpu, z_flag=True, h_flag=False, n_flag=True, c_flag=True) a.set(0x0F+1) - cpu.dec(a.get, a.set) + cpu.dec(RegisterCallWrapper(a), RegisterCallWrapper(a)) assert_default_flags(cpu, z_flag=False, h_flag=True, n_flag=True, c_flag=True) @@ -774,13 +774,13 @@ cpu.a.set(0) cpu.b.set(0) - cpu.add_a(cpu.b.get, cpu.b.set) + cpu.add_a(RegisterCallWrapper(cpu.b), None) assert_default_flags(cpu, z_flag=True, h_flag=False) cpu.reset() cpu.a.set(0x0F) cpu.b.set(0x01) - cpu.add_a(cpu.b.get, cpu.b.set) + cpu.add_a(RegisterCallWrapper(cpu.b), None) assert_default_flags(cpu, z_flag=False, h_flag=True) @@ -815,7 +815,7 @@ cpu.reset() a.set(0) b.set(0) - cpu.add_with_carry(b.get, b.set) + cpu.add_with_carry(RegisterCallWrapper(cpu.b), None) assert_default_registers(cpu, a=0, f=None) assert_default_flags(cpu, z_flag=True, c_flag=False, h_flag=False) @@ -823,14 +823,14 @@ a.set(0) b.set(0) cpu.f.c_flag = True - cpu.add_with_carry(b.get, b.set) + cpu.add_with_carry(RegisterCallWrapper(cpu.b), None) assert_default_registers(cpu, a=1, f=None) assert_default_flags(cpu, z_flag=False, c_flag=False, h_flag=False) cpu.reset() a.set(0xF0) b.set(0xFF) - cpu.add_with_carry(b.get, b.set) + cpu.add_with_carry(RegisterCallWrapper(cpu.b), None) # overflow for a assert_default_registers(cpu, a=0xEF, bc=None, f=None) assert_default_flags(cpu, z_flag=False, c_flag=True, h_flag=False) @@ -838,7 +838,7 @@ cpu.reset() a.set(0x0F) b.set(0x01) - cpu.add_with_carry(b.get, b.set) + cpu.add_with_carry(RegisterCallWrapper(cpu.b), None) assert_default_registers(cpu, a=0x10, f=None, bc=None) assert_default_flags(cpu, z_flag=False, c_flag=False, h_flag=True) @@ -901,7 +901,7 @@ cpu.reset() a.set(value) b.set(value) - cpu.subtract_with_carry(b.get, b.set) + cpu.subtract_with_carry(RegisterCallWrapper(cpu.b), None) assert_default_registers(cpu, a=0, bc=None, f=None) assert_default_flags(cpu, z_flag=True, c_flag=False, h_flag=False, n_flag=True) @@ -909,14 +909,14 @@ a.set(value) b.set(value-1) cpu.f.c_flag = True - cpu.subtract_with_carry(b.get, b.set) + cpu.subtract_with_carry(RegisterCallWrapper(cpu.b), None) assert_default_registers(cpu, a=0, bc=None, f=None) assert_default_flags(cpu, z_flag=True, c_flag=False, h_flag=False, n_flag=True) cpu.reset() a.set(0x20) b.set(0x01) - cpu.subtract_with_carry(b.get, b.set) + cpu.subtract_with_carry(RegisterCallWrapper(cpu.b), None) # overflow for a assert_default_registers(cpu, a=0x1F, bc=None, f=None) assert_default_flags(cpu, z_flag=False, c_flag=False, h_flag=True, n_flag=True) @@ -959,13 +959,13 @@ value = 0x12 cpu.a.set(value) cpu.b.set(value) - cpu.AND(cpu.b.get, cpu.b.set) + cpu.AND(RegisterCallWrapper(cpu.b), None) assert_default_flags(cpu, z_flag=False) cpu.reset() cpu.a.set(value) cpu.b.set(0) - cpu.AND(cpu.b.get, cpu.b.set) + cpu.AND(RegisterCallWrapper(cpu.b), None) assert_default_flags(cpu, z_flag=True) # and_A_B to and_A_A @@ -1000,13 +1000,13 @@ value = 0x12 cpu.a.set(value) cpu.b.set(value) - cpu.XOR(cpu.b.get, cpu.b.set) + cpu.XOR(RegisterCallWrapper(cpu.b), None) assert_default_flags(cpu, z_flag=True) cpu.reset() cpu.a.set(value) cpu.b.set(value+1) - cpu.XOR(cpu.b.get, cpu.b.set) + cpu.XOR(RegisterCallWrapper(cpu.b), None) assert_default_flags(cpu, z_flag=False) # xor_A_B to xor_A_A @@ -1040,13 +1040,13 @@ value = 0x12 cpu.a.set(value) cpu.b.set(value) - cpu.OR(cpu.b.get, cpu.b.set) + cpu.OR(RegisterCallWrapper(cpu.b), None) assert_default_flags(cpu, z_flag=False) cpu.reset() cpu.a.set(0) cpu.b.set(0) - cpu.OR(cpu.b.get, cpu.b.set) + cpu.OR(RegisterCallWrapper(cpu.b), None) assert_default_flags(cpu, z_flag=True) # or_A_B to or_A_A @@ -1080,19 +1080,19 @@ value = 0x12 cpu.a.set(value) cpu.b.set(value) - cpu.compare_a(cpu.b.get, cpu.b.set) + cpu.compare_a(RegisterCallWrapper(cpu.b), None) assert_default_flags(cpu, z_flag=True, n_flag=True) cpu.reset() cpu.a.set(value) cpu.b.set(0) - cpu.compare_a(cpu.b.get, cpu.b.set) + cpu.compare_a(RegisterCallWrapper(cpu.b), None) assert_default_flags(cpu, z_flag=False, n_flag=True) cpu.reset() cpu.a.set(0xF0) cpu.b.set(0x01) - cpu.compare_a(cpu.b.get, cpu.b.set) + cpu.compare_a(RegisterCallWrapper(cpu.b), None) assert_default_flags(cpu, z_flag=False, h_flag=True, n_flag=True) Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/video.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/video.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/video.py Sun May 18 18:12:40 2008 @@ -537,19 +537,19 @@ for i in range(0, 7): color = pattern >> (6-i) if (color & 0x0202) != 0: - caller(x+1, color, mask) + caller.call(x+1, color, mask) color = pattern << 1 if (color & 0x0202) != 0: - caller(x+7, color, mask) + caller.call(x+7, color, mask) def draw_object_flipped(self, x, pattern, mask, caller): color = pattern << 1 if (color & 0x0202) != 0: - caller(x, color, mask) + caller.call(x, color, mask) for i in range(0, 7): color = pattern >> i if (color & 0x0202) != 0: - caller(x + i + 1, color, mask) + caller.call(x + i + 1, color, mask) def draw_tile(self, x, address): pattern = self.get_pattern(address) @@ -557,14 +557,14 @@ self.line[x + i] = (pattern >> (7-i)) & 0x0101 def draw_object_tile(self, x, address, flags): - self.draw_object(set_tile_line_call_wrapper(self).call, x, address, \ + self.draw_object(set_tile_line_call_wrapper(self), x, address, \ flags) def set_tile_line(self, pos, color, mask): self.line[pos] |= color | mask def draw_overlapped_object_tile(self, x, address, flags): - self.draw_object(set_overlapped_object_line_call_wrapper(self).call, \ + self.draw_object(set_overlapped_object_line_call_wrapper(self), \ x, address, flags) def set_overlapped_object_line(self, pos, color, mask): From afa at codespeak.net Sun May 18 18:27:11 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Sun, 18 May 2008 18:27:11 +0200 (CEST) Subject: [pypy-svn] r54899 - in pypy/branch/win32port/pypy: config rlib rlib/test Message-ID: <20080518162711.E7C092A8004@codespeak.net> Author: afa Date: Sun May 18 18:27:11 2008 New Revision: 54899 Modified: pypy/branch/win32port/pypy/config/pypyoption.py pypy/branch/win32port/pypy/rlib/rmmap.py pypy/branch/win32port/pypy/rlib/test/test_rmmap.py Log: mmap is now a working_module on win32. The HANDLE type cannot be a voidp, because of some constants which are not addresses: INVALID_HANDLE = cast(HANDLE, -1) And the translator tries to translate this to a static array... now HANDLE == ULONG. Modified: pypy/branch/win32port/pypy/config/pypyoption.py ============================================================================== --- pypy/branch/win32port/pypy/config/pypyoption.py (original) +++ pypy/branch/win32port/pypy/config/pypyoption.py Sun May 18 18:27:11 2008 @@ -39,8 +39,6 @@ del working_modules["signal"] del working_modules["_rawffi"] # modules with broken windows support - del working_modules["mmap"] # MLS - Added 5/11/08 - broken - #del working_modules["_socket"] # MLS - Added 5/11/08 - broken del working_modules["select"] # MLS - Added 5/11/08 - broken Modified: pypy/branch/win32port/pypy/rlib/rmmap.py ============================================================================== --- pypy/branch/win32port/pypy/rlib/rmmap.py (original) +++ pypy/branch/win32port/pypy/rlib/rmmap.py Sun May 18 18:27:11 2008 @@ -47,8 +47,6 @@ PLONG = rffi_platform.SimpleType("PLONG", rffi.LONGP) LPVOID = rffi_platform.SimpleType("LPVOID", rffi.INTP) LPCVOID = rffi_platform.SimpleType("LPCVOID", rffi.VOIDP) - HANDLE = rffi_platform.SimpleType("HANDLE", rffi.VOIDP) - LPHANDLE = rffi_platform.SimpleType("LPHANDLE", rffi.CCHARPP) LPCTSTR = rffi_platform.SimpleType("LPCTSTR", rffi.CCHARP) LPDWORD = rffi_platform.SimpleType("LPDWORD", rffi.INTP) LPSECURITY_ATTRIBUTES = rffi_platform.SimpleType("LPSECURITY_ATTRIBUTES", rffi.CCHARP) @@ -82,6 +80,9 @@ for name in constant_names: setattr(CConfig, name, rffi_platform.ConstantInteger(name)) + HANDLE = rffi.ULONG + LPHANDLE = rffi.CArrayPtr(HANDLE) + # export the constants inside and outside. see __init__.py cConfig = rffi_platform.configure(CConfig) constants.update(cConfig) Modified: pypy/branch/win32port/pypy/rlib/test/test_rmmap.py ============================================================================== --- pypy/branch/win32port/pypy/rlib/test/test_rmmap.py (original) +++ pypy/branch/win32port/pypy/rlib/test/test_rmmap.py Sun May 18 18:27:11 2008 @@ -371,3 +371,16 @@ interpret(func, [f.fileno()]) f.close() + + def test_translated(self): + from pypy.translator.interactive import Translation + + def func(no): + m = mmap.mmap(no, 1) + r = m.read_byte() + m.close() + return r + + t = Translation(func) + fc = t.compile_c([int]) + From cami at codespeak.net Sun May 18 18:50:21 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Sun, 18 May 2008 18:50:21 +0200 (CEST) Subject: [pypy-svn] r54900 - in pypy/branch/gameboy-emulator/pypy: lang/gameboy lang/gameboy/test objspace/std rlib translator/goal Message-ID: <20080518165021.2A203168561@codespeak.net> Author: cami Date: Sun May 18 18:50:19 2008 New Revision: 54900 Added: pypy/branch/gameboy-emulator/pypy/rlib/rstr.py Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboy.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboyImplementation.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/interrupt.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cartridge.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_joypad.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_register.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_timer.py pypy/branch/gameboy-emulator/pypy/objspace/std/stringobject.py pypy/branch/gameboy-emulator/pypy/translator/goal/targetgbrom4.py Log: created rstr which can handle string replacement not only char replacement fixed some bugs which occured while translation translation starts to compile (which is a huge hurra for me) Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py Sun May 18 18:50:19 2008 @@ -7,6 +7,8 @@ from pypy.lang.gameboy.ram import iMemory +from pypy.rlib.rstr import str_replace + import os def has_cartridge_battery(self, cartridge_type): @@ -158,7 +160,7 @@ """ def __init__(self, file=None): self.reset() - if file != None: + if file is not None: self.load(file) def reset(self): @@ -191,12 +193,12 @@ def create_battery_file_path(self, cartridge_file_path): if cartridge_file_path.endswith(constants.CARTRIDGE_FILE_EXTENSION): - return cartridge_file_path.replace( \ + return str_replace(cartridge_file_path, constants.CARTRIDGE_FILE_EXTENSION, constants.BATTERY_FILE_EXTENSION) - elif cartridge_file_path.endswith(\ + elif cartridge_file_path.endswith( constants.CARTRIDGE_COLOR_FILE_EXTENSION): - return cartridge_file_path.replace( \ + return str_replace(cartridge_file_path, constants.CARTRIDGE_COLOR_FILE_EXTENSION, constants.BATTERY_FILE_EXTENSION) else: @@ -469,7 +471,7 @@ return self.clockLDays if self.clock_register == 0x0C: return self.clockLControl - raise Exception("invalid clockregister %i" % self.clock_register) + raise Exception("MBC*.read_clock_data invalid address %i") def write(self, address, data): if address <= 0x1FFF: # 0000-1FFF @@ -586,12 +588,15 @@ def write(self, address, data): - if address <= self.write_ram_enable: # 0000-1FFF + address = int(address) + if address <= self.ram_enable: # 0000-1FFF self.write_ram_enable(address, data) elif address <= 0x2FFF: # 2000-2FFF - self.rom_bank = ((self.rom_bank & (0x01 << 22)) + ((data & 0xFF) << 14)) & self.rom_size + self.rom_bank = ((self.rom_bank & (0x01 << 22)) + \ + ((data & 0xFF) << 14)) & self.rom_size elif address <= 0x3FFF: # 3000-3FFF - self.rom_bank = ((self.rom_bank & (0xFF << 14)) + ((data & 0x01) << 22)) & self.rom_size + self.rom_bank = ((self.rom_bank & (0xFF << 14)) + \ + ((data & 0x01) << 22)) & self.rom_size elif address <= 0x4FFF: # 4000-4FFF self.write_ram_bank(address, data) elif address >= 0xA000 and address <= 0xBFFF and self.ram_enable: # A000-BFFF Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboy.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboy.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboy.py Sun May 18 18:50:19 2008 @@ -80,8 +80,8 @@ self.draw_logo() def get_cycles(self): - return min( self.video.get_cycles(), self.serial.get_cycles(), - self.timer.get_cycles(), self.sound.get_cycles(), + return min(min(min(min( self.video.get_cycles(), self.serial.get_cycles()), + self.timer.get_cycles()), self.sound.get_cycles()), self.joypad.get_cycles()) def emulate(self, ticks): @@ -98,13 +98,13 @@ def write(self, address, data): receiver = self.get_receiver(address) - if receiver==None: + if receiver is None: raise Exception("invalid read address given") receiver.write(address, data) def read(self, address): receiver = self.get_receiver(address) - if receiver==None: + if receiver is None: raise Exception("invalid read address given") return receiver.read(address) Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboyImplementation.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboyImplementation.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboyImplementation.py Sun May 18 18:50:19 2008 @@ -101,12 +101,12 @@ def on_key_press(self, symbol, modifiers): pressButtonFunction = self.get_button_handler(symbol, modifiers) - if pressButtonFunction != None: + if pressButtonFunction is not None: pressButtonFunction(True) def on_key_release(self, symbol, modifiers): pressButtonFunction = self.get_button_handler(symbol, modifiers) - if pressButtonFunction != None: + if pressButtonFunction is not None: pressButtonFunction(False) def get_button_handler(self, symbol, modifiers): Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/interrupt.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/interrupt.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/interrupt.py Sun May 18 18:50:19 2008 @@ -60,7 +60,7 @@ def is_pending(self, mask=None): if not self.enable: return False - if mask==None: + if mask is None: return self.v_blank.is_pending() elif self.v_blank.is_pending(): return self.mask_mapping[mask].is_pending() Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cartridge.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cartridge.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_cartridge.py Sun May 18 18:50:19 2008 @@ -79,7 +79,7 @@ def test_cartridge_read(): cartridge = get_cartridge() - assert cartridge.read() == None + assert cartridge.read() is None def test_cartridge_remove_write_read_Battery(): Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_joypad.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_joypad.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_joypad.py Sun May 18 18:50:19 2008 @@ -31,7 +31,7 @@ assert number == i def number_to_bool_bin(number, size=None): - if size == None: + if size is None: if number == 0: return [] size = int(math.ceil(math.log(number, 2)))+1 @@ -46,7 +46,7 @@ def test_ini(): value = 0xf button = Button(value) - assert button.opposite_button == None + assert button.opposite_button is None assert button.code_value == value assert button.is_pressed() == False @@ -198,7 +198,7 @@ # TEST JOYPAD ------------------------------------------------------------------ def test_reset(joypad=None): - if joypad == None: + if joypad is None: joypad = get_joypad() assert joypad.joyp == 0xF assert joypad.cycles == constants.JOYPAD_CLOCK Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_register.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_register.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_register.py Sun May 18 18:50:19 2008 @@ -22,7 +22,7 @@ cpu.set_rom([0]*0xFFFF); return cpu global TEST_CPU - if TEST_CPU == None: + if TEST_CPU is None: TEST_CPU = get_cpu(True) TEST_CPU.reset() return TEST_CPU Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_timer.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_timer.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/test/test_timer.py Sun May 18 18:50:19 2008 @@ -12,7 +12,7 @@ def test_reset(timer=None): - if timer == None: + if timer is None: timer = get_timer() assert timer.div == 0 assert timer.divider_cycles == constants.DIV_CLOCK Modified: pypy/branch/gameboy-emulator/pypy/objspace/std/stringobject.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/objspace/std/stringobject.py (original) +++ pypy/branch/gameboy-emulator/pypy/objspace/std/stringobject.py Sun May 18 18:50:19 2008 @@ -15,6 +15,7 @@ stringendswith, stringstartswith, joined2 from pypy.objspace.std.formatting import mod_format +from pypy.rlib.rstr import str_replace class W_StringObject(W_Object): from pypy.objspace.std.stringtype import str_typedef as typedef @@ -474,32 +475,8 @@ sub = w_sub._value by = w_by._value maxsplit = space.int_w(w_maxsplit) - if maxsplit == 0: - return space.wrap(input) - #print "from replace, input: %s, sub: %s, by: %s" % (input, sub, by) - - if not sub: - upper = len(input) - if maxsplit > 0 and maxsplit < upper + 2: - upper = maxsplit - 1 - assert upper >= 0 - substrings = [""] - for i in range(upper): - c = input[i] - substrings.append(c) - substrings.append(input[upper:]) - return space.wrap(by.join(substrings)) - startidx = 0 - substrings = [] - foundidx = input.find(sub, startidx) - while foundidx >= 0 and maxsplit != 0: - substrings.append(input[startidx:foundidx]) - startidx = foundidx + len(sub) - foundidx = input.find(sub, startidx) - maxsplit = maxsplit - 1 - substrings.append(input[startidx:]) - return space.wrap(by.join(substrings)) + return space.wrap(str_replace(input, sub, by, maxsplit)) def _strip(space, w_self, w_chars, left, right): "internal function called by str_xstrip methods" Added: pypy/branch/gameboy-emulator/pypy/rlib/rstr.py ============================================================================== --- (empty file) +++ pypy/branch/gameboy-emulator/pypy/rlib/rstr.py Sun May 18 18:50:19 2008 @@ -0,0 +1,29 @@ + + +def str_replace(input, sub, by, maxsplit=-1): + if maxsplit == 0: + return input + + #print "from replace, input: %s, sub: %s, by: %s" % (input, sub, by) + + if not sub: + upper = len(input) + if maxsplit > 0 and maxsplit < upper + 2: + upper = maxsplit - 1 + assert upper >= 0 + substrings = [""] + for i in range(upper): + c = input[i] + substrings.append(c) + substrings.append(input[upper:]) + return by.join(substrings) + startidx = 0 + substrings = [] + foundidx = input.find(sub, startidx) + while foundidx >= 0 and maxsplit != 0: + substrings.append(input[startidx:foundidx]) + startidx = foundidx + len(sub) + foundidx = input.find(sub, startidx) + maxsplit = maxsplit - 1 + substrings.append(input[startidx:]) + return by.join(substrings) \ No newline at end of file Modified: pypy/branch/gameboy-emulator/pypy/translator/goal/targetgbrom4.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/translator/goal/targetgbrom4.py (original) +++ pypy/branch/gameboy-emulator/pypy/translator/goal/targetgbrom4.py Sun May 18 18:50:19 2008 @@ -22,7 +22,7 @@ #sys.setrecursionlimit(100000) -def entry_point(argv): +def entry_point(argv=None): if len(argv) > 1: filename = argv[1] else: @@ -30,7 +30,8 @@ gameBoy = GameBoy() #gameBoy.load_cartridge_file(ROM_PATH+"/rom4/rom4.gb")#filename) gameBoy.load_cartridge_file(str(filename)) - gameBoy.emulate(EMULATION_CYCLES) + return gameBoy.emulate(EMULATION_CYCLES) + # _____ Define and setup target ___ From cami at codespeak.net Sun May 18 19:07:58 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Sun, 18 May 2008 19:07:58 +0200 (CEST) Subject: [pypy-svn] r54901 - pypy/branch/gameboy-emulator/pypy/lang/gameboy Message-ID: <20080518170758.03F0F2A0180@codespeak.net> Author: cami Date: Sun May 18 19:07:56 2008 New Revision: 54901 Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboyImplementation.py Log: made thet gameboyimplemention compilable Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py Sun May 18 19:07:56 2008 @@ -52,6 +52,7 @@ assert isinstance(clock, Clock) self.clock = clock self.cartridge = None + self.mbc = None def reset(self): if not self.has_battery(): Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboyImplementation.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboyImplementation.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboyImplementation.py Sun May 18 19:07:56 2008 @@ -1,13 +1,6 @@ #!/usr/bin/env python import time -import pyglet -pyglet.options['audio'] = ('openal', 'silent') -from pyglet import window -from pyglet import media -from pyglet import image -from pyglet.window import key - from pypy.lang.gameboy.gameboy import * from pypy.lang.gameboy.joypad import JoypadDriver from pypy.lang.gameboy.video import VideoDriver @@ -21,11 +14,13 @@ def __init__(self): self.create_window() GameBoy.__init__(self) - self.mainLoop() + #self.mainLoop() def create_window(self): - self.win = window.Window() - self.win.set_caption("PyBoy a GameBoy (TM)") + self.win = None + #self.win = window.Window() + #self.win.set_caption("PyBoy a GameBoy (TM)") + pass def create_drivers(self): self.clock = Clock() @@ -46,28 +41,31 @@ def __init__(self, win): VideoDriver.__init__(self) - self.win = win - self.win.on_resize = self.on_resize - self.set_window_size() - self.create_image_buffer() + #self.win = win + #self.win.on_resize = self.on_resize + #self.set_window_size() + #self.create_image_buffer() def create_image_buffer(self): - self.buffers = image.get_buffer_manager() - self.image_buffer = self.buffers.get_color_buffer() - self.buffer_image_data = self.image_buffer.image_data - self.buffer_image_data.format = "RGB" - self.pixel_buffer = self.buffer_image_data.data - + #self.buffers = image.get_buffer_manager() + #self.image_buffer = self.buffers.get_color_buffer() + #self.buffer_image_data = self.image_buffer.image_data + #self.buffer_image_data.format = "RGB" + #self.pixel_buffer = self.buffer_image_data.data + pass + def on_resize(self, width, height): pass def set_window_size(self): - self.win.set_size(self.width, self.height) + #self.win.set_size(self.width, self.height) + pass def update_display(self): - self.buffer_image_data.data = map(self.pixel_to_byte, self.pixel_buffer) - self.image_buffer.blit(0, 0) - self.win.flip() + #self.buffer_image_data.data = map(self.pixel_to_byte, self.pixel_buffer) + #self.image_buffer.blit(0, 0) + #self.win.flip() + pass def pixel_to_byte(self, int_number): return struct.pack("B", (int_number) & 0xFF, @@ -81,9 +79,9 @@ def __init__(self, win): JoypadDriver.__init__(self) - self.create_button_key_codes() + #self.create_button_key_codes() self.win = win - self.create_listeners() + #self.create_listeners() def create_button_key_codes(self): self.button_key_codes = {key.UP : (self.button_up), @@ -147,6 +145,7 @@ def entry_point(args=None): gameboy = GameBoyImplementation() # add return statement... + return 0 # _____ Define and setup target ___ From tverwaes at codespeak.net Sun May 18 19:13:07 2008 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Sun, 18 May 2008 19:13:07 +0200 (CEST) Subject: [pypy-svn] r54902 - in pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk: . test Message-ID: <20080518171307.CC1C12A0180@codespeak.net> Author: tverwaes Date: Sun May 18 19:13:06 2008 New Revision: 54902 Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/primitives.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_interpreter.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_model.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_shadow.py Log: (cfbolz, tverwaes) cleaning up classes to use methoddict's shadow instead of local cache Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/primitives.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/primitives.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/primitives.py Sun May 18 19:13:06 2008 @@ -727,24 +727,36 @@ @expose_primitive(PRIMITIVE_SIGNAL, unwrap_spec=[object]) def func(interp, w_rcvr): - #if w_rcvr.getclass() != classtable.classtable['w_Semaphore']: + # XXX we might want to disable this check + if w_rcvr.getclass() is not classtable.classtable['w_Semaphore']: raise PrimitiveFailedError() - #assert isinstance(w_rcvr, model.W_PointersObject) - #w_rcvr.as_semaphore_get_shadow().synchronous_signal(interp) - #return w_rcvr + wrapper.SemaphoreWrapper(w_rcvr).signal(interp) + return w_rcvr @expose_primitive(PRIMITIVE_WAIT, unwrap_spec=[object]) def func(interp, w_rcvr): - raise PrimitiveNotYetWrittenError() + # XXX we might want to disable this check + if w_rcvr.getclass() is not classtable.classtable['w_Semaphore']: + raise PrimitiveFailedError() + wrapper.SemaphoreWrapper(w_rcvr).wait(interp) + return w_rcvr @expose_primitive(PRIMITIVE_RESUME, unwrap_spec=[object]) def func(interp, w_rcvr,): - raise PrimitiveNotYetWrittenError() - + # XXX we might want to disable this check + if w_rcvr.getclass() is not classtable.classtable['w_Process']: + raise PrimitiveFailedError() + wrapper.ProcessWrapper(w_rcvr).resume(interp) + return w_rcvr + @expose_primitive(PRIMITIVE_SUSPEND, unwrap_spec=[object]) def func(interp, w_rcvr): - raise PrimitiveNotYetWrittenError() - + # XXX we might want to disable this check + if w_rcvr.getclass() is not classtable.classtable['w_Process']: + raise PrimitiveFailedError() + wrapper.ProcessWrapper(w_rcvr).suspend(interp) + return w_rcvr + @expose_primitive(PRIMITIVE_FLUSH_CACHE, unwrap_spec=[object]) def func(interp, w_rcvr): # XXX we currently don't care about bad flushes :) XXX Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py Sun May 18 19:13:06 2008 @@ -86,7 +86,7 @@ def invalidate_shadow(self): AbstractShadow.invalidate_shadow(self) - self.methoddict = {} + self.w_methoddict = None self.s_superclass = None # the ClassShadow of the super class self.name = None @@ -154,11 +154,8 @@ if isinstance(w_name, model.W_BytesObject): self.name = w_name.as_string() # read the methoddict - w_methoddict = w_self._vars[constants.CLASS_METHODDICT_INDEX] - assert isinstance(w_methoddict, model.W_PointersObject) - s_methoddict = w_methoddict.as_methoddict_get_shadow() - self.methoddict = s_methoddict.methoddict - s_methoddict.notifyinvalid(self) + self.w_methoddict = w_self._vars[constants.CLASS_METHODDICT_INDEX] + assert isinstance(self.w_methoddict, model.W_PointersObject) # for the rest, we need to reset invalid to False already so # that cycles in the superclass and/or metaclass chains don't @@ -240,7 +237,7 @@ look_in_shadow = self while look_in_shadow is not None: try: - w_method = look_in_shadow.methoddict[selector] + w_method = look_in_shadow.s_methoddict().methoddict[selector] # We locally cache the method we found. #if look_in_shadow is not self: # self.methoddict[selector] = w_method @@ -249,18 +246,29 @@ look_in_shadow = look_in_shadow.s_superclass raise MethodNotFound(self, selector) + def s_methoddict(self): + return self.w_methoddict.as_methoddict_get_shadow() + + def initialize_methoddict(self): + "NOT_RPYTHON" # this is only for testing. + if self.w_methoddict is None: + self.w_methoddict = model.W_PointersObject(None, 2) + self.w_methoddict._vars[1] = model.W_PointersObject(None, 0) + self.s_methoddict().invalid = False + def installmethod(self, selector, method): "NOT_RPYTHON" # this is only for testing. - assert isinstance(method, model.W_CompiledMethod) - self.methoddict[selector] = method - method.w_compiledin = self.w_self() + self.initialize_methoddict() + self.s_methoddict().methoddict[selector] = method + if isinstance(method, model.W_CompiledMethod): + method.w_compiledin = self.w_self() class MethodDictionaryShadow(AbstractShadow): def __init__(self, w_self, invalid): AbstractShadow.__init__(self, w_self, invalid) def invalidate_shadow(self): - self.methoddict = {} + self.methoddict = None def update_shadow(self): from pypy.lang.smalltalk import objtable @@ -269,6 +277,7 @@ s_values = w_values.get_shadow() s_values.notifyinvalid(self) size = self.w_self().size() - constants.METHODDICT_NAMES_INDEX + self.methoddict = {} for i in range(size): w_selector = self.w_self()._vars[constants.METHODDICT_NAMES_INDEX+i] if w_selector is not objtable.w_nil: Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_interpreter.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_interpreter.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_interpreter.py Sun May 18 19:13:06 2008 @@ -36,13 +36,15 @@ prim_meth.argsize = argsize s_class.installmethod(methname, prim_meth) + assert objtable.w_nil._shadow is None try: func() finally: # Uninstall those methods: + assert objtable.w_nil._shadow is None for (w_class, _, _, methname) in methods: s_class = w_class.as_class_get_shadow() - del s_class.methoddict[methname] + del s_class.s_methoddict().methoddict[methname] def fakesymbol(s, _cache={}): try: @@ -402,7 +404,7 @@ assert interp.s_active_context().w_sender() == callerContext assert interp.s_active_context().stack() == [] assert interp.w_active_context().as_methodcontext_get_shadow().w_receiver() == w_object - assert interp.w_active_context().as_methodcontext_get_shadow().w_method() == shadow.methoddict["foo"] + assert interp.w_active_context().as_methodcontext_get_shadow().w_method() == shadow.s_methoddict().methoddict["foo"] assert callerContext.as_context_get_shadow().stack() == [] interp.step() interp.step() @@ -553,7 +555,7 @@ interp.s_active_context().push(w_object) interp.s_active_context().push(interp.ONE) interp.step() - assert interp.w_active_context().as_methodcontext_get_shadow().w_method() == shadow.methoddict["+"] + assert interp.w_active_context().as_methodcontext_get_shadow().w_method() == shadow.s_methoddict().methoddict["+"] assert interp.s_active_context().w_receiver() is w_object assert interp.w_active_context().as_methodcontext_get_shadow().gettemp(0) == interp.ONE assert interp.s_active_context().stack() == [] @@ -608,7 +610,7 @@ assert interp.s_active_context().w_sender() == callerContext assert interp.s_active_context().stack() == [] assert interp.w_active_context().as_methodcontext_get_shadow().w_receiver() == w_object - meth = w_specificclass.as_class_get_shadow().methoddict["foo"] + meth = w_specificclass.as_class_get_shadow().s_methoddict().methoddict["foo"] assert interp.w_active_context().as_methodcontext_get_shadow().w_method() == meth assert callerContext.as_context_get_shadow().stack() == [] Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_model.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_model.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_model.py Sun May 18 19:13:06 2008 @@ -56,12 +56,14 @@ def test_method_lookup(): w_class = mockclass(0) shadow = w_class.as_class_get_shadow() - shadow.methoddict["foo"] = 1 - shadow.methoddict["bar"] = 2 + shadow.installmethod("foo", 1) + shadow.installmethod("bar", 2) w_subclass = mockclass(0, w_superclass=w_class) subshadow = w_subclass.as_class_get_shadow() assert subshadow.s_superclass is shadow - subshadow.methoddict["foo"] = 3 + subshadow.installmethod("foo", 3) + shadow.initialize_methoddict() + subshadow.initialize_methoddict() assert shadow.lookup("foo") == 1 assert shadow.lookup("bar") == 2 py.test.raises(MethodNotFound, shadow.lookup, "zork") @@ -76,6 +78,7 @@ supershadow = w_super.as_class_get_shadow() supershadow.installmethod("foo", model.W_CompiledMethod(0)) classshadow = w_class.as_class_get_shadow() + classshadow.initialize_methoddict() assert classshadow.lookup("foo").w_compiledin is w_super def test_compiledmethod_setchar(): Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_shadow.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_shadow.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_shadow.py Sun May 18 19:13:06 2008 @@ -67,7 +67,7 @@ 'bar': model.W_CompiledMethod(0)} w_class = build_smalltalk_class("Demo", 0x90, methods=methods) classshadow = w_class.as_class_get_shadow() - assert classshadow.methoddict == methods + assert classshadow.s_methoddict().methoddict == methods def method(tempsize=3,argsize=2, bytes="abcde"): w_m = model.W_CompiledMethod() From afa at codespeak.net Sun May 18 19:48:12 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Sun, 18 May 2008 19:48:12 +0200 (CEST) Subject: [pypy-svn] r54903 - in pypy/branch/win32port/pypy: config rlib rlib/test Message-ID: <20080518174812.3D0D22A0180@codespeak.net> Author: afa Date: Sun May 18 19:48:11 2008 New Revision: 54903 Modified: pypy/branch/win32port/pypy/config/pypyoption.py pypy/branch/win32port/pypy/rlib/rpoll.py pypy/branch/win32port/pypy/rlib/test/test_rpoll.py Log: 'select' is now a working_module on win32. This one was easy. Modified: pypy/branch/win32port/pypy/config/pypyoption.py ============================================================================== --- pypy/branch/win32port/pypy/config/pypyoption.py (original) +++ pypy/branch/win32port/pypy/config/pypyoption.py Sun May 18 19:48:11 2008 @@ -38,8 +38,6 @@ # modules currently missing explicit windows support del working_modules["signal"] del working_modules["_rawffi"] - # modules with broken windows support - del working_modules["select"] # MLS - Added 5/11/08 - broken Modified: pypy/branch/win32port/pypy/rlib/rpoll.py ============================================================================== --- pypy/branch/win32port/pypy/rlib/rpoll.py (original) +++ pypy/branch/win32port/pypy/rlib/rpoll.py Sun May 18 19:48:11 2008 @@ -8,6 +8,7 @@ import os from pypy.rlib import _rsocket_rffi as _c from pypy.rpython.lltypesystem import lltype, rffi +from pypy.rlib.rarithmetic import intmask, r_uint # ____________________________________________________________ # events @@ -121,7 +122,7 @@ if ret == _c.WSA_WAIT_TIMEOUT: return [] - if ret == _c.WSA_WAIT_FAILED: + if ret == r_uint(_c.WSA_WAIT_FAILED): raise PollError(_c.geterrno()) retval = [] Modified: pypy/branch/win32port/pypy/rlib/test/test_rpoll.py ============================================================================== --- pypy/branch/win32port/pypy/rlib/test/test_rpoll.py (original) +++ pypy/branch/win32port/pypy/rlib/test/test_rpoll.py Sun May 18 19:48:11 2008 @@ -47,3 +47,12 @@ cli.close() servconn.close() serv.close() + +def test_translate(): + from pypy.translator.interactive import Translation + + def func(): + poll({}) + + t = Translation(func) + fc = t.compile_c([]) From arigo at codespeak.net Sun May 18 19:51:03 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 18 May 2008 19:51:03 +0200 (CEST) Subject: [pypy-svn] r54904 - pypy/dist/pypy/config Message-ID: <20080518175103.1157A2A0180@codespeak.net> Author: arigo Date: Sun May 18 19:51:01 2008 New Revision: 54904 Modified: pypy/dist/pypy/config/pypyoption.py Log: Disable this temporarily, because it is invalid so far (depending on the point of view, it's a bug in the multimethods or in the way we abuse them) Modified: pypy/dist/pypy/config/pypyoption.py ============================================================================== --- pypy/dist/pypy/config/pypyoption.py (original) +++ pypy/dist/pypy/config/pypyoption.py Sun May 18 19:51:01 2008 @@ -290,7 +290,7 @@ "special case the 'list[integer]' expressions", default=False), BoolOption("builtinshortcut", - "a shortcut for operations between built-in types", + "a shortcut for operations between built-in types XXX BROKEN", default=False), BoolOption("getattributeshortcut", "track types that override __getattribute__", @@ -322,7 +322,7 @@ ("objspace.std.withmethodcache", True), # ("objspace.std.withfastslice", True), ("objspace.std.withprebuiltchar", True), - ("objspace.std.builtinshortcut", True), +# ("objspace.std.builtinshortcut", True), ("objspace.std.optimized_list_getitem", True), ("objspace.std.getattributeshortcut", True), ("translation.list_comprehension_operations",True), From tverwaes at codespeak.net Sun May 18 20:41:07 2008 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Sun, 18 May 2008 20:41:07 +0200 (CEST) Subject: [pypy-svn] r54905 - in pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk: . test Message-ID: <20080518184107.76A5D169E24@codespeak.net> Author: tverwaes Date: Sun May 18 20:41:06 2008 New Revision: 54905 Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/constants.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/primitives.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_miniimage.py Log: -also load smalltalk into the objtable. -adding start for a smalltalk commandline Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/constants.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/constants.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/constants.py Sun May 18 20:41:06 2008 @@ -128,6 +128,8 @@ "false": SO_FALSE, "charactertable": SO_CHARACTER_TABLE_ARRAY, "schedulerassociationpointer" : SO_SCHEDULERASSOCIATIONPOINTER, + "compactclasses" : SO_COMPACT_CLASSES_ARRAY, + "smalltalkdict" : SO_SMALLTALK, } TAGGED_MAXINT = 2 ** (LONG_BIT - 2) - 1 Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/primitives.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/primitives.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/primitives.py Sun May 18 20:41:06 2008 @@ -8,6 +8,7 @@ from pypy.lang.smalltalk.error import PrimitiveFailedError, \ PrimitiveNotYetWrittenError from pypy.rlib import rarithmetic, unroll +from pypy.lang.smalltalk import wrapper def assert_bounds(n0, minimum, maximum): Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_miniimage.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_miniimage.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_miniimage.py Sun May 18 20:41:06 2008 @@ -285,4 +285,8 @@ #print interp.s_active_context.stack except interpreter.ReturnFromTopLevel, e: return e.object - + +#def test_eval(): +# w_smalltalk = objtable.objtable["w_smalltalkdict"] +# w_utilities_class = perform(w_smalltalk, "classNamed:", w("Utilities")) +# perform(w_utilities_class, "eval:", w("Transcript show: 1+2")) From pypy-svn at codespeak.net Sun May 18 21:21:10 2008 From: pypy-svn at codespeak.net (VIAGRA ® Official Site) Date: Sun, 18 May 2008 21:21:10 +0200 (CEST) Subject: [pypy-svn] Dear pypy-svn@codespeak.net May 87% 0FF Message-ID: <20020518101700.6654.qmail@ajw100.neoplus.adsl.tpnet.pl> An HTML attachment was scrubbed... URL: From fijal at codespeak.net Sun May 18 22:18:21 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 18 May 2008 22:18:21 +0200 (CEST) Subject: [pypy-svn] r54906 - pypy/branch/hybrid-io/pypy/rpython/memory/gc Message-ID: <20080518201821.A74012A00DC@codespeak.net> Author: fijal Date: Sun May 18 22:18:19 2008 New Revision: 54906 Modified: pypy/branch/hybrid-io/pypy/rpython/memory/gc/hybrid.py Log: Check for necessary collects in case of realloc as well Modified: pypy/branch/hybrid-io/pypy/rpython/memory/gc/hybrid.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/memory/gc/hybrid.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/memory/gc/hybrid.py Sun May 18 22:18:19 2008 @@ -241,6 +241,7 @@ self.gen_resizable_objects.append(result + size_gc_header) else: self.gen2_rawmalloced_objects.append(result + size_gc_header) + self._check_rawsize_alloced(tot_size) (result + size_gc_header + lengthofs).signed[0] = newsize return llmemory.cast_adr_to_ptr(result + size_gc_header, llmemory.GCREF) @@ -266,14 +267,7 @@ totalsize) return result - def malloc_varsize_marknsweep(self, totalsize, resizable=False): - # In order to free the large objects from time to time, we - # arbitrarily force a full collect() if none occurs when we have - # allocated 'self.space_size' bytes of large objects. - # XXX we should probably track the total raw_malloc'ed size - # XXX and adjust sizes based on it; otherwise we risk doing - # XXX many many collections if the program allocates a lot - # XXX more than the current self.space_size. + def _check_rawsize_alloced(self, totalsize): self.large_objects_collect_trigger -= raw_malloc_usage(totalsize) if self.large_objects_collect_trigger < 0: if DEBUG_PRINT: @@ -282,6 +276,16 @@ self.large_objects_collect_trigger, "bytes, triggering full collection") self.semispace_collect() + + def malloc_varsize_marknsweep(self, totalsize, resizable=False): + # In order to free the large objects from time to time, we + # arbitrarily force a full collect() if none occurs when we have + # allocated 'self.space_size' bytes of large objects. + # XXX we should probably track the total raw_malloc'ed size + # XXX and adjust sizes based on it; otherwise we risk doing + # XXX many many collections if the program allocates a lot + # XXX more than the current self.space_size. + self._check_rawsize_alloced(totalsize) result = self.allocate_external_object(totalsize) if not result: raise MemoryError() From antocuni at codespeak.net Sun May 18 22:32:21 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Sun, 18 May 2008 22:32:21 +0200 (CEST) Subject: [pypy-svn] r54907 - in pypy/branch/oo-jit/pypy/rpython/ootypesystem: . test Message-ID: <20080518203221.43E432A00DC@codespeak.net> Author: antocuni Date: Sun May 18 22:32:20 2008 New Revision: 54907 Modified: pypy/branch/oo-jit/pypy/rpython/ootypesystem/ootype.py pypy/branch/oo-jit/pypy/rpython/ootypesystem/test/test_ootype.py Log: make sure all null _object are identical Modified: pypy/branch/oo-jit/pypy/rpython/ootypesystem/ootype.py ============================================================================== --- pypy/branch/oo-jit/pypy/rpython/ootypesystem/ootype.py (original) +++ pypy/branch/oo-jit/pypy/rpython/ootypesystem/ootype.py Sun May 18 22:32:20 2008 @@ -812,7 +812,8 @@ def __init__(self, obj): self._TYPE = Object - self.obj = obj or None # null obj ==> None + assert obj is None or obj, 'Cannot create _object of a null value, use make_object() instead' + self.obj = obj def __nonzero__(self): return self.obj is not None @@ -868,7 +869,7 @@ self._INSTANCE = INSTANCE def _cast_to_object(self): - return _object(self) + return make_object(self) nullruntimeclass = _class(None) @@ -940,7 +941,7 @@ return 0 # for all null instances def _cast_to_object(self): - return _object(ooupcast(ROOT, self)) + return make_object(ooupcast(ROOT, self)) def _null_mixin(klass): @@ -1055,7 +1056,7 @@ return self._inst._identityhash() def _cast_to_object(self): - return _object(ooupcast(ROOT, self)) + return make_object(ooupcast(ROOT, self)) if STATICNESS: instance_impl = _view @@ -1082,6 +1083,12 @@ inst = _view(INSTANCE, inst) return inst +def make_object(llvalue): + if llvalue: + return _object(llvalue) + else: + return NULL + class _callable(object): def __init__(self, TYPE, **attrs): @@ -1120,7 +1127,7 @@ return hash(frozendict(self.__dict__)) def _cast_to_object(self): - return _object(self) + return make_object(self) class _static_meth(_callable): @@ -1164,7 +1171,7 @@ return callb(self.inst, *checked_args) def _cast_to_object(self): - return _object(self) + return make_object(self) class _meth(_callable): @@ -1294,7 +1301,7 @@ return object.__getattribute__(self, name) def _cast_to_object(self): - return _object(self) + return make_object(self) class _string(_builtin_type): @@ -1709,7 +1716,7 @@ return not (self == other) def _cast_to_object(self): - return _object(self) + return make_object(self) class _null_record(_null_mixin(_record), _record): Modified: pypy/branch/oo-jit/pypy/rpython/ootypesystem/test/test_ootype.py ============================================================================== --- pypy/branch/oo-jit/pypy/rpython/ootypesystem/test/test_ootype.py (original) +++ pypy/branch/oo-jit/pypy/rpython/ootypesystem/test/test_ootype.py Sun May 18 22:32:20 2008 @@ -574,7 +574,8 @@ b = null(B) obj1 = cast_to_object(a) obj2 = cast_to_object(b) - assert obj1 == obj2 + assert obj1 is obj2 + assert obj1 is NULL assert cast_from_object(A, obj1) == a assert cast_from_object(B, obj2) == b From bgola at codespeak.net Sun May 18 22:51:28 2008 From: bgola at codespeak.net (bgola at codespeak.net) Date: Sun, 18 May 2008 22:51:28 +0200 (CEST) Subject: [pypy-svn] r54908 - pypy/branch/2.5-features/pypy/interpreter/pyparser/test Message-ID: <20080518205128.CC37E2A00DC@codespeak.net> Author: bgola Date: Sun May 18 22:51:27 2008 New Revision: 54908 Modified: pypy/branch/2.5-features/pypy/interpreter/pyparser/test/expressions.py pypy/branch/2.5-features/pypy/interpreter/pyparser/test/test_astbuilder.py Log: fixing tests for astbuilder (empty base classes list can be empty) Modified: pypy/branch/2.5-features/pypy/interpreter/pyparser/test/expressions.py ============================================================================== --- pypy/branch/2.5-features/pypy/interpreter/pyparser/test/expressions.py (original) +++ pypy/branch/2.5-features/pypy/interpreter/pyparser/test/expressions.py Sun May 18 22:51:27 2008 @@ -361,9 +361,7 @@ one_stmt_classdefs = [ "class Pdb(bdb.Bdb, cmd.Cmd): pass", - "class A(): pass", "class A: pass", - "class A)(: x", ] docstrings = [ @@ -484,6 +482,10 @@ ## ["l = [i for i in range(10) if i%2 == 0 or i%2 == 1]"], ## ] +CHANGES_25_INPUTS = [ + ["class A(): pass"], + ] + EXEC_INPUTS = [ one_stmt_classdefs, one_stmt_funcdefs, Modified: pypy/branch/2.5-features/pypy/interpreter/pyparser/test/test_astbuilder.py ============================================================================== --- pypy/branch/2.5-features/pypy/interpreter/pyparser/test/test_astbuilder.py (original) +++ pypy/branch/2.5-features/pypy/interpreter/pyparser/test/test_astbuilder.py Sun May 18 22:51:27 2008 @@ -14,7 +14,7 @@ from pypy.interpreter.astcompiler import ast from fakes import FakeSpace -from expressions import TESTS, SINGLE_INPUTS, EXEC_INPUTS +from expressions import TESTS, SINGLE_INPUTS, EXEC_INPUTS, CHANGES_25_INPUTS def arglist_equal(left,right): """needs special case because we handle the argumentlist differently""" @@ -168,6 +168,9 @@ "a[100, 1:]": "Module(None, Stmt([Discard(Subscript(Name('a'), 2, Tuple([Const(100), Sliceobj([Const(1), Const(None)])])))]))", "a[100, :2,]": "Module(None, Stmt([Discard(Subscript(Name('a'), 2, Tuple([Const(100), Sliceobj([Const(None), Const(2)])])))]))", "a[100, :]": "Module(None, Stmt([Discard(Subscript(Name('a'), 2, Tuple([Const(100), Sliceobj([Const(None), Const(None)])])))]))", + + # stablecompiler can't produce AST for 2.5 syntax (yet) + "class A(): pass": "Module(None, Stmt([Class('A', [], None, Stmt([Pass()]))]))", # stablecompiler produces a Pass statement which does not seem very consistent # (a module should only have a Stmt child) @@ -181,15 +184,14 @@ t = Transformer("dummyfile") return ast_from_input(expr, target, t, stable_parser) -def source2ast(source, mode, space=FakeSpace()): - version = '2.4' +def source2ast(source, mode, space=FakeSpace(), version='2.4'): python_parser = pythonparse.make_pyparser(version) builder = AstBuilder(python_parser, version, space=space) python_parser.parse_source(source, mode, builder) return builder.rule_stack[-1] -def check_expression(expr, mode='single'): - pypy_ast = source2ast(expr, mode) +def check_expression(expr, mode='single', version='2.4'): + pypy_ast = source2ast(expr, mode, version=version) try: python_ast = EXPECTED[expr] except KeyError: @@ -219,6 +221,10 @@ for expr in family: yield check_expression, expr, 'exec' +def test_changes_25(): + for family in CHANGES_25_INPUTS: + for expr in family: + yield check_expression, expr, 'exec', '2.5' NEW_GRAMMAR_SNIPPETS = [ 'snippet_with_1.py', @@ -266,7 +272,7 @@ ] def test_snippets(): - for snippet_name in SNIPPETS: # + NEW_GRAMMAR_SNIPPETS: # Disabled 2.5 syntax + for snippet_name in SNIPPETS: # + NEW_GRAMMAR_SNIPPETS: filepath = os.path.join(os.path.dirname(__file__), 'samples', snippet_name) source = file(filepath).read() # To avoid using the stable compiler we pull an explicit AST out of the snippet From antocuni at codespeak.net Sun May 18 22:56:04 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Sun, 18 May 2008 22:56:04 +0200 (CEST) Subject: [pypy-svn] r54909 - in pypy/branch/oo-jit/pypy: rpython/test translator/oosupport translator/oosupport/test_template Message-ID: <20080518205604.696702A0180@codespeak.net> Author: antocuni Date: Sun May 18 22:56:00 2008 New Revision: 54909 Modified: pypy/branch/oo-jit/pypy/rpython/test/test_rclass.py pypy/branch/oo-jit/pypy/translator/oosupport/constant.py pypy/branch/oo-jit/pypy/translator/oosupport/test_template/class_.py Log: add support for pbc of type ootype.Object to oo backends; add a new test for it. Modified: pypy/branch/oo-jit/pypy/rpython/test/test_rclass.py ============================================================================== --- pypy/branch/oo-jit/pypy/rpython/test/test_rclass.py (original) +++ pypy/branch/oo-jit/pypy/rpython/test/test_rclass.py Sun May 18 22:56:00 2008 @@ -870,5 +870,21 @@ return obj else: return ootype.NULL - res = self.interpret(fn_mix_null, [False]) - assert res is ootype.NULL + res = self.interpret(fn_mix_null, [True]) + assert res + + def test_cast_object_pbc(self): + A = ootype.Instance("Foo", ootype.ROOT, {"x": ootype.Signed}) + a1 = ootype.new(A) + a1.x = 42 + obj1 = ootype.cast_to_object(a1) + def fn(flag): + if flag: + obj = obj1 + else: + obj = ootype.NULL + a = ootype.cast_from_object(A, obj) + return a.x + res = self.interpret(fn, [True], backendopt=False) + assert res == 42 + Modified: pypy/branch/oo-jit/pypy/translator/oosupport/constant.py ============================================================================== --- pypy/branch/oo-jit/pypy/translator/oosupport/constant.py (original) +++ pypy/branch/oo-jit/pypy/translator/oosupport/constant.py Sun May 18 22:56:00 2008 @@ -188,7 +188,10 @@ """ A helper method which creates a Constant wrapper object for the given value. Uses the types defined in the sub-class. """ - + + if isinstance(value, ootype._object) and value: # leave ootype.NULL as is + value = value.obj + # Determine if the static type differs from the dynamic type. if isinstance(value, ootype._view): static_type = value._TYPE Modified: pypy/branch/oo-jit/pypy/translator/oosupport/test_template/class_.py ============================================================================== --- pypy/branch/oo-jit/pypy/translator/oosupport/test_template/class_.py (original) +++ pypy/branch/oo-jit/pypy/translator/oosupport/test_template/class_.py Sun May 18 22:56:00 2008 @@ -1,8 +1,8 @@ import py -from pypy.rpython.test.test_rclass import BaseTestRclass +from pypy.rpython.test import test_rclass from pypy.rpython.test.test_rspecialcase import BaseTestRspecialcase -class BaseTestClass(BaseTestRclass): +class BaseTestClass(test_rclass.TestOOtype): def test_abstract_method(self): class Base: pass From antocuni at codespeak.net Sun May 18 23:11:16 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Sun, 18 May 2008 23:11:16 +0200 (CEST) Subject: [pypy-svn] r54910 - in pypy/branch/oo-jit/pypy: jit/codegen/cli translator/cli translator/oosupport Message-ID: <20080518211116.9572A16845E@codespeak.net> Author: antocuni Date: Sun May 18 23:11:14 2008 New Revision: 54910 Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/operation.py pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py pypy/branch/oo-jit/pypy/translator/cli/opcodes.py pypy/branch/oo-jit/pypy/translator/oosupport/constant.py Log: yai! test_gencli_portal.test_very_simple passes :-) Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/operation.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/codegen/cli/operation.py (original) +++ pypy/branch/oo-jit/pypy/jit/codegen/cli/operation.py Sun May 18 23:11:14 2008 @@ -177,6 +177,23 @@ self.storeResult() +class SetField(Operation): + + def __init__(self, builder, gv_obj, gv_value, fieldname): + self.builder = builder + self.gv_obj = gv_obj + self.gv_value = gv_value + clitype = gv_obj.getCliType() + self.fieldinfo = clitype.GetField(fieldname) + + def restype(self): + return None + + def emit(self): + self.gv_obj.load(self.builder) + self.gv_value.load(self.builder) + self.builder.graphbuilder.il.Emit(OpCodes.Stfld, self.fieldinfo) + def opcode2attrname(opcode): if opcode == 'ldc.r8 0': return 'Ldc_R8, 0' # XXX this is a hack Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py (original) +++ pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py Sun May 18 23:11:14 2008 @@ -208,7 +208,11 @@ @specialize.arg(1) def revealconst(self, T): assert isinstance(T, ootype.OOType) - return unbox(self.holder.GetFunc(), T) + if isinstance(T, ootype.StaticMethod): + return unbox(self.holder.GetFunc(), T) + else: + assert T is ootype.Object + return ootype.cast_to_object(self.holder.GetFunc()) class Label(GenLabel): def __init__(self, label, inputargs_gv): @@ -373,6 +377,9 @@ def genop_oogetfield(self, fieldtoken, gv_obj): return self.branches[0].genop_oogetfield(fieldtoken, gv_obj) + def genop_oosetfield(self, fieldtoken, gv_obj, gv_value): + return self.branches[0].genop_oosetfield(fieldtoken, gv_obj, gv_value) + def end(self): # render all the pending branches for branchbuilder in self.branches: @@ -450,8 +457,9 @@ self.appendop(op) return op.gv_res() -## def genop_oosetfield(self, fieldtoken, gv_obj, gv_value): -## pass + def genop_oosetfield(self, fieldtoken, gv_obj, gv_value): + op = ops.SetField(self, gv_obj, gv_value, fieldtoken) + self.appendop(op) def enter_next_block(self, args_gv): for i in range(len(args_gv)): Modified: pypy/branch/oo-jit/pypy/translator/cli/opcodes.py ============================================================================== --- pypy/branch/oo-jit/pypy/translator/cli/opcodes.py (original) +++ pypy/branch/oo-jit/pypy/translator/cli/opcodes.py Sun May 18 23:11:14 2008 @@ -72,6 +72,7 @@ 'gc__disable_finalizers': Ignore, 'resume_point': Ignore, 'debug_assert': Ignore, + 'debug_print': Ignore, 'keepalive': Ignore, 'is_early_constant': [PushPrimitive(ootype.Bool, False)], } Modified: pypy/branch/oo-jit/pypy/translator/oosupport/constant.py ============================================================================== --- pypy/branch/oo-jit/pypy/translator/oosupport/constant.py (original) +++ pypy/branch/oo-jit/pypy/translator/oosupport/constant.py Sun May 18 23:11:14 2008 @@ -191,6 +191,7 @@ if isinstance(value, ootype._object) and value: # leave ootype.NULL as is value = value.obj + self.db.cts.lltype_to_cts(value._TYPE) # record const # Determine if the static type differs from the dynamic type. if isinstance(value, ootype._view): From fijall at gmail.com Sun May 18 23:21:15 2008 From: fijall at gmail.com (Maciej Fijalkowski) Date: Sun, 18 May 2008 23:21:15 +0200 Subject: [pypy-svn] r54903 - in pypy/branch/win32port/pypy: config rlib rlib/test In-Reply-To: <20080518174812.3D0D22A0180@codespeak.net> References: <20080518174812.3D0D22A0180@codespeak.net> Message-ID: <693bc9ab0805181421s4ea08ddree0b326ffb2c6be6@mail.gmail.com> > +def test_translate(): > + from pypy.translator.interactive import Translation > + > + def func(): > + poll({}) > + > + t = Translation(func) > + fc = t.compile_c([]) wuaa. Please use from pypy.translator.c.test.test_genc import compile and use this one. Cheers, fijal From afa at codespeak.net Mon May 19 00:03:42 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Mon, 19 May 2008 00:03:42 +0200 (CEST) Subject: [pypy-svn] r54912 - pypy/branch/win32port/pypy/rlib/test Message-ID: <20080518220342.CB41A169E3B@codespeak.net> Author: afa Date: Mon May 19 00:03:40 2008 New Revision: 54912 Modified: pypy/branch/win32port/pypy/rlib/test/test_rmmap.py pypy/branch/win32port/pypy/rlib/test/test_rpoll.py Log: update tests to use the simpler compile() function. Thanks Maciej. Modified: pypy/branch/win32port/pypy/rlib/test/test_rmmap.py ============================================================================== --- pypy/branch/win32port/pypy/rlib/test/test_rmmap.py (original) +++ pypy/branch/win32port/pypy/rlib/test/test_rmmap.py Mon May 19 00:03:40 2008 @@ -373,7 +373,7 @@ f.close() def test_translated(self): - from pypy.translator.interactive import Translation + from pypy.translator.c.test.test_genc import compile def func(no): m = mmap.mmap(no, 1) @@ -381,6 +381,4 @@ m.close() return r - t = Translation(func) - fc = t.compile_c([int]) - + compile(func, [int]) Modified: pypy/branch/win32port/pypy/rlib/test/test_rpoll.py ============================================================================== --- pypy/branch/win32port/pypy/rlib/test/test_rpoll.py (original) +++ pypy/branch/win32port/pypy/rlib/test/test_rpoll.py Mon May 19 00:03:40 2008 @@ -49,10 +49,9 @@ serv.close() def test_translate(): - from pypy.translator.interactive import Translation + from pypy.translator.c.test.test_genc import compile def func(): poll({}) - t = Translation(func) - fc = t.compile_c([]) + compile(func, []) From cfbolz at codespeak.net Mon May 19 10:16:38 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Mon, 19 May 2008 10:16:38 +0200 (CEST) Subject: [pypy-svn] r54913 - pypy/extradoc/talk/s3-2008 Message-ID: <20080519081638.8FDB016840F@codespeak.net> Author: cfbolz Date: Mon May 19 10:16:35 2008 New Revision: 54913 Added: pypy/extradoc/talk/s3-2008/talk-squeakev.pdf (contents, props changed) pypy/extradoc/talk/s3-2008/talk-squeakev.tex Log: the talk we gave at the squeak e.V. meeting Added: pypy/extradoc/talk/s3-2008/talk-squeakev.pdf ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/s3-2008/talk-squeakev.tex ============================================================================== --- (empty file) +++ pypy/extradoc/talk/s3-2008/talk-squeakev.tex Mon May 19 10:16:35 2008 @@ -0,0 +1,234 @@ +\documentclass[utf8x]{beamer} + +\mode +{ + \usetheme{Warsaw} + + %\setbeamercovered{transparent} +} + + +\usepackage[english]{babel} + +\usepackage[utf8x]{inputenc} + +\usepackage{times} +\usepackage[T1]{fontenc} + +\title[Back to the Future in one Week] +{% + Back to the Future in one Week ? Implementing a Smalltalk VM in PyPy% +} + +\author[Bolz, Kuhn, Lienhard, Matsakis, Nierstrasz, Renggli, Rigo, Verwaest] +{ + \textcolor{green!50!black}{Carl~Friedrich~Bolz}\inst{1} \and + \textcolor{green!50!black}{Adrian~Kuhn\inst{2}} \and + Adrian~Lienhard\inst{2} \and + Nicholas~D.~Matsakis\inst{3} \and + Oscar~Nierstrasz\inst{2} \and + Lukas~Renggli\inst{2} \and + Armin~Rigo \and + \textcolor{green!50!black}{Toon~Verwaest}\inst{2} +} + +\institute[Bern and others] +{ + \inst{2}% + Software Composition Group\\ University of Bern, Switzerland + \and% + \vskip-2mm + \inst{1} + Softwaretechnik und Programmiersprachen\\ Heinrich-Heine-Universit\"at D\"usseldorf + \and% + \vskip-2mm + \inst{3}% + ETH Z?rich, Switzerland +} + + +\date{Squeak e.V. Meeting, May 17 2008 \\ +(presented at S3) +} + + +% Delete this, if you do not want the table of contents to pop up at +% the beginning of each subsection: +%\AtBeginSubsection[] +%{ +% \begin{frame} +% \frametitle{Outline} +% \tableofcontents[currentsection,currentsubsection] +% \end{frame} +%} + + +% If you wish to uncover everything in a step-wise fashion, uncomment +% the following command: + +%\beamerdefaultoverlayspecification{<+->} + + +\begin{document} + +\begin{frame} + \titlepage +\end{frame} + +%\begin{frame} +% \frametitle{Outline} +% \tableofcontents + % You might wish to add the option [pausesections] +%\end{frame} + +\begin{frame} + \frametitle{Scope} + This demo is about: + \begin{itemize} + \item writing a Squeak implementation (called "SPy") in Python + \item with eight people + \item in five days + \item using PyPy + \end{itemize} +\end{frame} + +\begin{frame} + \frametitle{What is PyPy?} + \begin{itemize} + \item started as a Python implementation in Python + \item Open Source project, MIT license + \item developed into a general environment for implementing dynamic languages + \item supports the language developer with a lot of infrastructure + \item most important goal: abstracting over low-level details + \item don't fix decisions about low-level details early + \end{itemize} +\end{frame} + +\frame[plain]{ + \frametitle{What is PyPy?} + \centering + \includegraphics[height=8cm]{dynlang} +} +\begin{frame} + \frametitle{The SPy VM} + \begin{itemize} + \item complete but simple, straight-forward Squeak interpreter in RPython + \item goal is to fully support loading and running Squeak images + \item source code essentially free of low-level details, no GC + \item written during a five-day sprint in October in Bern + \end{itemize} +\end{frame} + +\begin{frame} + \frametitle{Current Status} + \begin{itemize} + \item bytecodes fully implemented + \item many primitives implemented: arithmetic primitives, object primitives + \item can load Squeak images (both 2.0 and 3.9) + \item runs tiny benchmarks + \item runs arbitrary code + \item resume image + \end{itemize} + \pause + Open Issues: + \begin{itemize} + \item any I/O + \item graphics + \item performance + \item \#someInstance, \#nextInstance + \item \#become + \item tests for threading and exceptions + \end{itemize} +\end{frame} + +\frame[containsverbatim, plain, shrink=10]{ + \begin{verbatim} + primitiveSquareRoot + | rcvr | + self var: #rcvr type: 'double '. + rcvr := self popFloat. + self success: rcvr >= 0.0. + successFlag + ifTrue: [self pushFloat: + (self cCode: 'sqrt(rcvr)' + inSmalltalk: [rcvr sqrt])] + ifFalse: [self unPop: 1] + + + + + + + + + + \end{verbatim} +} + + +\frame[containsverbatim, plain, shrink=10]{ + \begin{verbatim} + primitiveSquareRoot + | rcvr | + self var: #rcvr type: 'double '. + rcvr := self popFloat. + self success: rcvr >= 0.0. + successFlag + ifTrue: [self pushFloat: + (self cCode: 'sqrt(rcvr)' + inSmalltalk: [rcvr sqrt])] + ifFalse: [self unPop: 1] + + + @expose_primitive(FLOAT_SQUARE_ROOT, + unwrap_spec=[float]) +def func(interp, f): + if f < 0.0: + raise PrimitiveFailedError + w_res = utility.wrap_float(math.sqrt(f)) + return w_res + \end{verbatim} +} + +\frame[plain]{ + \frametitle{Performance (tiny Benchmark)} + \centering + \includegraphics[height=8cm]{speed} +} + +\begin{frame} + \frametitle{Results} + {\bf Good Points of the Approach:} + \begin{itemize} + \item simple, understandable, high-level Squeak implementation + \item mostly free of low-level details: no GC, no manual pointer tagging + \item written in a short amount of time + \item runs on various platforms + \item extensible tool chain + \end{itemize} + \pause + {\bf Bad Points of the Approach:} + \begin{itemize} + \item not really fast (yet) + \item RPython isn't Python + \end{itemize} +\end{frame} + +\begin{frame} + \frametitle{Outlook} + \begin{itemize} + \item do graphical builtins, to actually start the full environment + \item Squeak-specific optimizations: + \item method-cache (should be easy with shadows) + \item JIT + \item lessons learned for a "SqueaSquea"? + \end{itemize} + \begin{block}{ + Join the Sprint!} + \bigskip + \hskip 1cm Saturday - Thursday, C-Base Berlin + \bigskip + \end{block} +\end{frame} + +\end{document} From cfbolz at codespeak.net Mon May 19 10:33:19 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Mon, 19 May 2008 10:33:19 +0200 (CEST) Subject: [pypy-svn] r54914 - pypy/extradoc/sprintinfo/berlin-2008 Message-ID: <20080519083319.EFC6E2A0180@codespeak.net> Author: cfbolz Date: Mon May 19 10:33:19 2008 New Revision: 54914 Modified: pypy/extradoc/sprintinfo/berlin-2008/planning.txt Log: (all): planning Modified: pypy/extradoc/sprintinfo/berlin-2008/planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/berlin-2008/planning.txt (original) +++ pypy/extradoc/sprintinfo/berlin-2008/planning.txt Mon May 19 10:33:19 2008 @@ -20,21 +20,24 @@ Tasks: - - gameboy emulator: trying to translate, lots of blocked blocks (Armin looking, Camillo) - - adding sdl bindings to rpython (Camillo, Karl, Armin) IN-PROGRESS + - gameboy emulator translation DONE + - adding sdl bindings to rpython (Camillo, Stephan) MORE PROGRESS: mouse movement works now too - django porting: using django with sqlite-ctypes works (Samuele, Maciek) 90/200 tests failing - more robustapply work - dictionary subclassing - - making sqlite-ctypes work on PyPy DONE (mostly) + more robustapply work: turned out to be an sqlite problem + dictionary subclassing: found the problem, unclear how to fix + - making sqlite-ctypes work on PyPy DONE - hybrid-io-improvements branch: discussions happened - - work on SPy, decide about the branch (Toon, Carl Friedrich) + - work on SPy, decide about the branch (Toon, Carl Friedrich) IN-PROGRESS work on sanitizing the spy shadow branch - - complete Stackless interface (Stephan, Peter) - work on channel preferences - some cleanup needed - - discussions/starting on separate compilation (Armin, Samuele, Maciek, Alexander) + - complete Stackless interface + work on channel preferences DONE + some cleanup needed DONE + - discussion about composable coroutines DONE + - discussions/starting on separate compilation - discuss our own GCs and threads + - discussion about the JIT + - trying to run Zope 3 a bit (Armin, Peter) - work on PyPy's JIT generator: we are refactoring parts of the From arigo at codespeak.net Mon May 19 11:03:44 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 19 May 2008 11:03:44 +0200 (CEST) Subject: [pypy-svn] r54917 - pypy/dist/pypy/doc/discussion Message-ID: <20080519090344.47DE72A00E0@codespeak.net> Author: arigo Date: Mon May 19 11:03:42 2008 New Revision: 54917 Added: pypy/dist/pypy/doc/discussion/testing-zope.txt (contents, props changed) Log: Document how to checkout and run the Zope tests. (Thanks Holger for the basics) Added: pypy/dist/pypy/doc/discussion/testing-zope.txt ============================================================================== --- (empty file) +++ pypy/dist/pypy/doc/discussion/testing-zope.txt Mon May 19 11:03:42 2008 @@ -0,0 +1,45 @@ +Testing Zope on top of pypy-c +============================= + +Getting Zope packages +--------------------- + +If you don't have a full Zope installation, you can pick a Zope package, +check it out via Subversion, and get all its dependencies (replace +``$PKG`` with, for example, ``zope.interface``):: + + svn co svn://svn.zope.org/repos/main/$PKG/trunk $PKG + cd $PKG + python bootstrap.py + bin/buildout + bin/test + +Required pypy-c version +----------------------- + +You probably need a pypy-c built with --allworkingmodules, at least:: + + cd pypy/translator/goal + ./translate.py targetpypystandalone.py --allworkingmodules + +Workarounds +----------- + +At the moment, our ``gc`` module is incomplete, making the Zope test +runner unhappy. Quick workaround: go to the +``lib-python/modified-2.4.1`` directory and create a +``sitecustomize.py`` with the following content:: + + print "" + import gc + gc.get_threshold = lambda : (0, 0, 0) + gc.get_debug = lambda : 0 + gc.garbage = [] + +Running the tests +----------------- + +To run the tests we need the --oldstyle option, as follows:: + + cd $PKG + pypy-c --oldstyle bin/test From tverwaes at codespeak.net Mon May 19 11:23:00 2008 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Mon, 19 May 2008 11:23:00 +0200 (CEST) Subject: [pypy-svn] r54919 - in pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk: . test Message-ID: <20080519092300.7EA6616852C@codespeak.net> Author: tverwaes Date: Mon May 19 11:22:58 2008 New Revision: 54919 Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/classtable.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/interpreter.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_miniimage.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_model.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_shadow.py Log: (cfbolz, tverwaes) cleaned up superclass link in classshadow Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/classtable.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/classtable.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/classtable.py Mon May 19 11:22:58 2008 @@ -9,7 +9,7 @@ s = shadow.ClassShadow(w_class, True) s.methoddict = {} if w_superclass is not None: - s.s_superclass = w_superclass.as_class_get_shadow() + s.w_superclass = w_superclass s.name = name s.instance_size = instsize s.instance_kind = format @@ -65,8 +65,8 @@ define_core_cls(cls_nm, classtable[super_cls_nm], w_metacls) w_Class = classtable["w_Class"] w_Metaclass = classtable["w_Metaclass"] - w_ProtoObjectClass.as_class_get_shadow().s_superclass = \ - w_Class.as_class_get_shadow() + w_ProtoObjectClass.as_class_get_shadow().w_superclass = \ + w_Class # at this point, all classes that still lack a w_class are themselves # metaclasses for nm, w_cls_obj in classtable.items(): Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/interpreter.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/interpreter.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/interpreter.py Mon May 19 11:22:58 2008 @@ -197,7 +197,7 @@ assert isinstance(w_compiledin, model.W_PointersObject) s_compiledin = w_compiledin.as_class_get_shadow() self._sendSelector(selector, argcount, interp, self.w_receiver(), - s_compiledin.s_superclass) + s_compiledin.s_superclass()) def _sendSelector(self, selector, argcount, interp, receiver, receiverclassshadow): Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py Mon May 19 11:22:58 2008 @@ -87,7 +87,7 @@ def invalidate_shadow(self): AbstractShadow.invalidate_shadow(self) self.w_methoddict = None - self.s_superclass = None # the ClassShadow of the super class + self.w_superclass = None self.name = None def getname(self): @@ -141,6 +141,8 @@ else: w_name = None + # Some heuristic to find the classname + # Only used for debugging # XXX This is highly experimental XXX # if the name-pos of class is not bytesobject, # we are probably holding a metaclass instead of a class. @@ -156,16 +158,11 @@ # read the methoddict self.w_methoddict = w_self._vars[constants.CLASS_METHODDICT_INDEX] assert isinstance(self.w_methoddict, model.W_PointersObject) - - # for the rest, we need to reset invalid to False already so - # that cycles in the superclass and/or metaclass chains don't - # cause infinite recursion - # read s_superclass w_superclass = w_self._vars[constants.CLASS_SUPERCLASS_INDEX] - if w_superclass is not objtable.w_nil: - assert isinstance(w_superclass, model.W_PointersObject) - self.s_superclass = w_superclass.as_class_get_shadow() - self.s_superclass.notifyinvalid(self) + if w_superclass is objtable.w_nil: + self.w_superclass = None + else: + self.w_superclass = w_superclass AbstractShadow.update_shadow(self) # XXX check better way to store objects @@ -190,6 +187,14 @@ objtable.objects.extend([w_new]) return w_new + def s_methoddict(self): + return self.w_methoddict.as_methoddict_get_shadow() + + def s_superclass(self): + if self.w_superclass is None: + return None + return self.w_superclass.as_class_get_shadow() + # _______________________________________________________________ # Methods for querying the format word, taken from the blue book: # @@ -223,7 +228,7 @@ while classshadow is not None: if classshadow is s_superclass: return True - classshadow = classshadow.s_superclass + classshadow = classshadow.s_superclass() else: return False @@ -238,17 +243,11 @@ while look_in_shadow is not None: try: w_method = look_in_shadow.s_methoddict().methoddict[selector] - # We locally cache the method we found. - #if look_in_shadow is not self: - # self.methoddict[selector] = w_method return w_method except KeyError, e: - look_in_shadow = look_in_shadow.s_superclass + look_in_shadow = look_in_shadow.s_superclass() raise MethodNotFound(self, selector) - def s_methoddict(self): - return self.w_methoddict.as_methoddict_get_shadow() - def initialize_methoddict(self): "NOT_RPYTHON" # this is only for testing. if self.w_methoddict is None: Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_miniimage.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_miniimage.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_miniimage.py Mon May 19 11:22:58 2008 @@ -285,8 +285,3 @@ #print interp.s_active_context.stack except interpreter.ReturnFromTopLevel, e: return e.object - -#def test_eval(): -# w_smalltalk = objtable.objtable["w_smalltalkdict"] -# w_utilities_class = perform(w_smalltalk, "classNamed:", w("Utilities")) -# perform(w_utilities_class, "eval:", w("Transcript show: 1+2")) Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_model.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_model.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_model.py Mon May 19 11:22:58 2008 @@ -60,7 +60,7 @@ shadow.installmethod("bar", 2) w_subclass = mockclass(0, w_superclass=w_class) subshadow = w_subclass.as_class_get_shadow() - assert subshadow.s_superclass is shadow + assert subshadow.s_superclass() is shadow subshadow.installmethod("foo", 3) shadow.initialize_methoddict() subshadow.initialize_methoddict() Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_shadow.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_shadow.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_shadow.py Mon May 19 11:22:58 2008 @@ -49,7 +49,7 @@ assert classshadow.isvariable() == varsized assert classshadow.instsize() == instsize assert classshadow.name == name - assert classshadow.s_superclass is w_Object.as_class_get_shadow() + assert classshadow.s_superclass() is w_Object.as_class_get_shadow() def test_basic_shape(): yield basicshape, "Empty", 0x02, shadow.POINTERS, False, 0 From cami at codespeak.net Mon May 19 11:28:25 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Mon, 19 May 2008 11:28:25 +0200 (CEST) Subject: [pypy-svn] r54920 - in pypy/dist/pypy/rlib/rsdl: . test Message-ID: <20080519092825.0097516852C@codespeak.net> Author: cami Date: Mon May 19 11:28:24 2008 New Revision: 54920 Modified: pypy/dist/pypy/rlib/rsdl/RSDL.py pypy/dist/pypy/rlib/rsdl/constants.py pypy/dist/pypy/rlib/rsdl/test/test_video.py Log: added mouse tests formatted source code Modified: pypy/dist/pypy/rlib/rsdl/RSDL.py ============================================================================== --- pypy/dist/pypy/rlib/rsdl/RSDL.py (original) +++ pypy/dist/pypy/rlib/rsdl/RSDL.py Mon May 19 11:28:24 2008 @@ -20,90 +20,184 @@ ) eci = eci.merge(ExternalCompilationInfo.from_config_tool('sdl-config')) +# ------------------------------------------------------------------------------ + def external(name, args, result): return rffi.llexternal(name, args, result, compilation_info=eci) -RectPtr = lltype.Ptr(lltype.ForwardReference()) -SurfacePtr = lltype.Ptr(lltype.ForwardReference()) -PixelFormatPtr = lltype.Ptr(lltype.ForwardReference()) -EventPtr = lltype.Ptr(lltype.ForwardReference()) -KeyboardEventPtr = lltype.Ptr(lltype.ForwardReference()) +# ------------------------------------------------------------------------------ + +RectPtr = lltype.Ptr(lltype.ForwardReference()) +SurfacePtr = lltype.Ptr(lltype.ForwardReference()) +PixelFormatPtr = lltype.Ptr(lltype.ForwardReference()) +EventPtr = lltype.Ptr(lltype.ForwardReference()) +KeyboardEventPtr = lltype.Ptr(lltype.ForwardReference()) +MouseButtonEventPtr = lltype.Ptr(lltype.ForwardReference()) +MouseMotionEventPtr = lltype.Ptr(lltype.ForwardReference()) + +# ------------------------------------------------------------------------------ class CConfig: _compilation_info_ = eci Uint8 = platform.SimpleType('Uint8', rffi.INT) Uint16 = platform.SimpleType('Uint16', rffi.INT) + Sint16 = platform.SimpleType('Sint16', rffi.INT) Uint32 = platform.SimpleType('Uint32', rffi.INT) - Rect = platform.Struct('SDL_Rect', [('x', rffi.INT), - ('y', rffi.INT), - ('w', rffi.INT), - ('h', rffi.INT)]) - Surface = platform.Struct('SDL_Surface', [('w', rffi.INT), - ('h', rffi.INT), - ('format', PixelFormatPtr), - ('pitch', rffi.INT), - ('pixels', rffi.UCHARP)]) - PixelFormat = platform.Struct('SDL_PixelFormat', - [('BytesPerPixel', rffi.INT)]) - - Event = platform.Struct('SDL_Event', [('type', rffi.INT)]) - keysym = platform.Struct('SDL_keysym', [('scancode', rffi.INT), - ('sym', rffi.INT), - ('mod', rffi.INT), - ('unicode', rffi.INT)]) - KeyboardEvent = platform.Struct('SDL_KeyboardEvent', + Rect = platform.Struct('SDL_Rect', + [('x', rffi.INT), + ('y', rffi.INT), + ('w', rffi.INT), + ('h', rffi.INT)]) + + Surface = platform.Struct('SDL_Surface', + [('w', rffi.INT), + ('h', rffi.INT), + ('format', PixelFormatPtr), + ('pitch', rffi.INT), + ('pixels', rffi.UCHARP)]) + + PixelFormat = platform.Struct('SDL_PixelFormat', + [('BytesPerPixel', rffi.INT)]) + + Event = platform.Struct('SDL_Event', + [('type', rffi.INT)]) + + keysym = platform.Struct('SDL_keysym', + [('scancode', rffi.INT), + ('sym', rffi.INT), + ('mod', rffi.INT), + ('unicode', rffi.INT)]) + + KeyboardEvent = platform.Struct('SDL_KeyboardEvent', [('type', rffi.INT), ('state', rffi.INT), ('keysym', keysym)]) + + MouseButtonEvent = platform.Struct('SDL_MouseButtonEvent', + [('type', rffi.INT), + ('button', rffi.INT), + ('state', rffi.INT), + ('x', rffi.INT), + ('y', rffi.INT)]) + + MouseMotionEvent = platform.Struct('SDL_MouseMotionEvent', + [('type', rffi.INT), + ('state', rffi.INT), + ('x', rffi.INT), + ('y', rffi.INT), + ('xrel', rffi.INT), + ('yrel', rffi.INT)]) + + +# ------------------------------------------------------------------------------ for _prefix, _list in _constants.items(): for _name in _list: setattr(CConfig, _name, platform.ConstantInteger(_prefix+_name)) +# ------------------------------------------------------------------------------ + globals().update(platform.configure(CConfig)) +# ------------------------------------------------------------------------------ + RectPtr.TO.become(Rect) SurfacePtr.TO.become(Surface) PixelFormatPtr.TO.become(PixelFormat) EventPtr.TO.become(Event) KeyboardEventPtr.TO.become(KeyboardEvent) +MouseButtonEventPtr.TO.become(MouseButtonEvent) +MouseMotionEventPtr.TO.become(MouseMotionEvent) -Uint8P = lltype.Ptr(lltype.Array(Uint8, hints={'nolength': True})) +# ------------------------------------------------------------------------------ + +Uint8P = lltype.Ptr(lltype.Array(Uint8, hints={'nolength': True})) Uint16P = lltype.Ptr(lltype.Array(Uint16, hints={'nolength': True})) +# need to add signed hint here +Sint16P = lltype.Ptr(lltype.Array(Sint16, hints={'nolength': True})) Uint32P = lltype.Ptr(lltype.Array(Uint32, hints={'nolength': True})) +# ------------------------------------------------------------------------------ + def Init(flags): if sys.platform == 'darwin': from AppKit import NSApplication NSApplication.sharedApplication() return _Init(flags) -_Init = external('SDL_Init', [Uint32], rffi.INT) -Quit = external('SDL_Quit', [], lltype.Void) -SetVideoMode = external('SDL_SetVideoMode', [rffi.INT, rffi.INT, - rffi.INT, Uint32], - SurfacePtr) -WM_SetCaption = external('SDL_WM_SetCaption', [rffi.CCHARP, rffi.CCHARP], - lltype.Void) -EnableUNICODE = external('SDL_EnableUNICODE', [rffi.INT], rffi.INT) -WaitEvent = external('SDL_WaitEvent', [EventPtr], rffi.INT) -Flip = external('SDL_Flip', [SurfacePtr], rffi.INT) -CreateRGBSurface = external('SDL_CreateRGBSurface', [Uint32, rffi.INT, - rffi.INT, rffi.INT, - Uint32, Uint32, - Uint32, Uint32], - SurfacePtr) -LockSurface = external('SDL_LockSurface', [SurfacePtr], rffi.INT) -UnlockSurface = external('SDL_UnlockSurface', [SurfacePtr], lltype.Void) -FreeSurface = external('SDL_FreeSurface', [SurfacePtr], lltype.Void) - -MapRGB = external('SDL_MapRGB', [PixelFormatPtr, Uint8, Uint8, Uint8], Uint32) -GetRGB = external('SDL_GetRGB', [Uint32, PixelFormatPtr, - Uint8P, Uint8P, Uint8P], lltype.Void) -GetRGBA = external('SDL_GetRGBA', [Uint32, PixelFormatPtr, - Uint8P, Uint8P, Uint8P, Uint8P], lltype.Void) -FillRect = external('SDL_FillRect', [SurfacePtr, RectPtr, Uint32], rffi.INT) -BlitSurface = external('SDL_UpperBlit', [SurfacePtr, RectPtr, SurfacePtr, RectPtr], rffi.INT) -SetAlpha = external('SDL_SetAlpha', [SurfacePtr, Uint32, Uint8], rffi.INT) +# ------------------------------------------------------------------------------ + +_Init = external('SDL_Init', + [Uint32], + rffi.INT) + +Quit = external('SDL_Quit', [], + lltype.Void) + +SetVideoMode = external('SDL_SetVideoMode', + [rffi.INT, rffi.INT, rffi.INT, Uint32], + SurfacePtr) + +WM_SetCaption = external('SDL_WM_SetCaption', + [rffi.CCHARP, rffi.CCHARP], + lltype.Void) + +EnableUNICODE = external('SDL_EnableUNICODE', + [rffi.INT], + rffi.INT) + +WaitEvent = external('SDL_WaitEvent', + [EventPtr], + rffi.INT) + +Flip = external('SDL_Flip', + [SurfacePtr], + rffi.INT) + +CreateRGBSurface = external('SDL_CreateRGBSurface', + [Uint32, rffi.INT, rffi.INT, rffi.INT, + Uint32, Uint32, Uint32, Uint32], + SurfacePtr) + +LockSurface = external('SDL_LockSurface', + [SurfacePtr], + rffi.INT) + +UnlockSurface = external('SDL_UnlockSurface', + [SurfacePtr], + lltype.Void) + +FreeSurface = external('SDL_FreeSurface', + [SurfacePtr], + lltype.Void) + +MapRGB = external('SDL_MapRGB', + [PixelFormatPtr, Uint8, Uint8, Uint8], + Uint32) + +GetRGB = external('SDL_GetRGB', + [Uint32, PixelFormatPtr, Uint8P, Uint8P, Uint8P], + lltype.Void) + +GetRGBA = external('SDL_GetRGBA', + [Uint32, PixelFormatPtr, Uint8P, Uint8P, + Uint8P, Uint8P], + lltype.Void) + +FillRect = external('SDL_FillRect', + [SurfacePtr, RectPtr, Uint32], + rffi.INT) + +BlitSurface = external('SDL_UpperBlit', + [SurfacePtr, RectPtr, SurfacePtr, RectPtr], + rffi.INT) + +SetAlpha = external('SDL_SetAlpha', + [SurfacePtr, Uint32, Uint8], + rffi.INT) + +ShowCursor = external('SDL_ShowCursor', + [rffi.INT], + rffi.INT) Modified: pypy/dist/pypy/rlib/rsdl/constants.py ============================================================================== --- pypy/dist/pypy/rlib/rsdl/constants.py (original) +++ pypy/dist/pypy/rlib/rsdl/constants.py Mon May 19 11:28:24 2008 @@ -48,6 +48,10 @@ "MOUSEMOTION", "MOUSEBUTTONDOWN", "MOUSEBUTTONUP", + "BUTTON_LEFT", + "BUTTON_LEFT", + "BUTTON_MIDDLE", + "BUTTON_RIGHT", "JOYAXISMOTION", "JOYBALLMOTION", "JOYHATMOTION", @@ -69,6 +73,9 @@ "HAT_LEFTDOWN", "HAT_LEFT", "HAT_LEFTUP", + + "DISABLE", + "ENABLE", # the following ones are not exposed in Pygame "INIT_VIDEO", Modified: pypy/dist/pypy/rlib/rsdl/test/test_video.py ============================================================================== --- pypy/dist/pypy/rlib/rsdl/test/test_video.py (original) +++ pypy/dist/pypy/rlib/rsdl/test/test_video.py Mon May 19 11:28:24 2008 @@ -1,3 +1,4 @@ + import py, sys from pypy.rlib.rsdl import RSDL from pypy.rlib.rarithmetic import r_uint @@ -54,28 +55,110 @@ RSDL.EnableUNICODE(1) print print "Keys pressed in the Pygame window should be printed below." - print "Use Escape to quit." - while True: - event = lltype.malloc(RSDL.Event, flavor='raw') - try: + print " Use Escape to quit." + event = lltype.malloc(RSDL.Event, flavor='raw') + try: + while True: + ok = RSDL.WaitEvent(event) + assert rffi.cast(lltype.Signed, ok) == 1 + c_type = rffi.getintfield(event, 'c_type') + if c_type == RSDL.KEYDOWN: + p = rffi.cast(RSDL.KeyboardEventPtr, event) + if rffi.getintfield(p.c_keysym, 'c_sym') == RSDL.K_ESCAPE: + print 'Escape key' + break + char = rffi.getintfield(p.c_keysym, 'c_unicode') + if char != 0: + print 'Key:', unichr(char).encode('utf-8') + else: + print 'Some special key' + else: + print '(event of type %d)' % c_type + finally: + lltype.free(event, flavor='raw') + + + def test_mousemove(self): + if not self.is_interactive: + py.test.skip("interactive test only") + print + print "Move the Mouse up and down:" + print " Use Escape to quit." + event = lltype.malloc(RSDL.Event, flavor="raw") + directions = [False]*4 + try: + while True: ok = RSDL.WaitEvent(event) assert rffi.cast(lltype.Signed, ok) == 1 - c_type = rffi.getintfield(event, 'c_type') - if c_type == RSDL.KEYDOWN: + c_type = rffi.getintfield(event, "c_type") + if c_type == RSDL.MOUSEMOTION: + m = rffi.cast(RSDL.MouseMotionEventPtr, event) + assert rffi.getintfield(m, "c_x") >= 0 + assert rffi.getintfield(m, "c_y") >= 0 + print rffi.getintfield(m, "c_xrel") + directions[0] |= rffi.getintfield(m, "c_xrel")>0 + directions[1] |= rffi.getintfield(m, "c_xrel")<0 + directions[2] |= rffi.getintfield(m, "c_yrel")>0 + directions[3] |= rffi.getintfield(m, "c_yrel")<0 + if False not in directions: + break + elif c_type == RSDL.KEYUP: p = rffi.cast(RSDL.KeyboardEventPtr, event) if rffi.getintfield(p.c_keysym, 'c_sym') == RSDL.K_ESCAPE: - print 'Escape key' - break - char = rffi.getintfield(p.c_keysym, 'c_unicode') - if char != 0: - print 'Key:', unichr(char).encode('utf-8') - else: - print 'Some special key' - else: - print '(event of type %d)' % c_type - finally: - lltype.free(event, flavor='raw') + print " test manually aborted" + py.test.fail(" mousemovement test aborted") + break + finally: + lltype.free(event, flavor='raw') + + + + def test_mousebutton(self): + if not self.is_interactive: + py.test.skip("interactive test only") + print + print "Press the given MouseButtons:" + print " Use Escape to quit." + + event_tests = [("left button", RSDL.BUTTON_LEFT), + ("middle button", RSDL.BUTTON_MIDDLE), + ("right button", RSDL.BUTTON_RIGHT)] + test_success = [] + event = lltype.malloc(RSDL.Event, flavor='raw') + try: + for button_test in event_tests: + print " press %s:" % button_test[0] + while True: + ok = RSDL.WaitEvent(event) + assert rffi.cast(lltype.Signed, ok) == 1 + c_type = rffi.getintfield(event, 'c_type') + if c_type == RSDL.MOUSEBUTTONDOWN: + pass + elif c_type == RSDL.MOUSEBUTTONUP: + b = rffi.cast(RSDL.MouseButtonEventPtr, event) + if rffi.getintfield(b, 'c_button') == button_test[1]: + test_success.append(True) + break + elif c_type == RSDL.KEYUP: + p = rffi.cast(RSDL.KeyboardEventPtr, event) + if rffi.getintfield(p.c_keysym, 'c_sym') == RSDL.K_ESCAPE: + test_success.append(False) + print " manually aborted" + break + #break + if False in test_success: + py.test.fail("") + finally: + lltype.free(event, flavor='raw') + + + def test_show_hide_cursor(self): + RSDL.ShowCursor(RSDL.DISABLE) + self.check("Is the cursor hidden? ") + RSDL.ShowCursor(RSDL.ENABLE) + self.check("Is the cursor shown? ") + def test_blit_rect(self): surface = RSDL.CreateRGBSurface(0, 150, 50, 32, r_uint(0x000000FF), @@ -85,6 +168,15 @@ fmt = surface.c_format color = RSDL.MapRGB(fmt, 255, 0, 0) RSDL.FillRect(surface, lltype.nullptr(RSDL.Rect), color) + + paintrect = lltype.malloc(RSDL.Rect, flavor='raw') + rffi.setintfield(paintrect, 'c_x', 75) + rffi.setintfield(paintrect, 'c_y', 0) + rffi.setintfield(paintrect, 'c_w', 150) + rffi.setintfield(paintrect, 'c_h', 50) + color = RSDL.MapRGB(fmt, 255, 128, 0) + RSDL.FillRect(surface, paintrect, color) + dstrect = lltype.malloc(RSDL.Rect, flavor='raw') try: rffi.setintfield(dstrect, 'c_x', 10) @@ -96,7 +188,7 @@ finally: lltype.free(dstrect, flavor='raw') RSDL.FreeSurface(surface) - self.check("Red rectangle(150px * 50px) at the top left, 10 pixels from the border") + self.check("Half Red/Orange rectangle(150px * 50px) at the top left, 10 pixels from the border") def teardown_method(self, meth): RSDL.Quit() From fijal at codespeak.net Mon May 19 12:06:34 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 19 May 2008 12:06:34 +0200 (CEST) Subject: [pypy-svn] r54921 - pypy/django/tests Message-ID: <20080519100634.6B28C16853D@codespeak.net> Author: fijal Date: Mon May 19 12:06:31 2008 New Revision: 54921 Added: pypy/django/tests/conftest.py (contents, props changed) Log: (pedronis, fijal) start of conftest for django tests Added: pypy/django/tests/conftest.py ============================================================================== --- (empty file) +++ pypy/django/tests/conftest.py Mon May 19 12:06:31 2008 @@ -0,0 +1,48 @@ + +import py +import os + +# XXX ignores invalid models path + +rootdir = py.path.local(__file__).dirpath() + +DIRNAMES = ['modeltests', 'regressiontests']#, 'django/contrib'] + +class Directory(py.test.collect.Directory): + def run(self): + rel = self.fspath.relto(rootdir) + if not rel: + self.level = 0 + return self.run0() + lgt = rel.count(os.path.sep) + if lgt == 0: + self.level = 1 + return self.run1() + else: + self.level = 2 + return self.run2() + + def run2(self): + return [] + + def run1(self): + models = [] + for model in self.fspath.listdir(): + f = str(model.basename) + if f.startswith('__init__') or f.startswith('.') or f.startswith('sql') or f.startswith('invalid'): + pass + else: + models.append(f) + models.sort() + return models + + def run0(self): + return DIRNAMES + + def join(self, name): + path = self.fspath.join(name) + if path.check(dir=1): + return Directory(self.fspath.join(name)) + else: + explode + From tverwaes at codespeak.net Mon May 19 12:14:42 2008 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Mon, 19 May 2008 12:14:42 +0200 (CEST) Subject: [pypy-svn] r54922 - in pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk: . test Message-ID: <20080519101442.5310B16853F@codespeak.net> Author: tverwaes Date: Mon May 19 12:14:40 2008 New Revision: 54922 Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/objtable.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/primitives.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/squeakimage.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_model.py Log: (cfbolz, arigo, tverwaes) removed ugly become. Enabled become for PointersObjects only, which is -very- fast (does not go over the image) Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py Mon May 19 12:14:40 2008 @@ -89,12 +89,12 @@ def equals(self, other): """Compare object identity""" - return self == other + return self is other - def become(self, w_old, w_new): - """Exchange object identity.""" - # TODO use PyPy's become - pass + def become(self, other): + """Become swaps two objects. + False means swapping failed""" + return False class W_SmallInteger(W_Object): """Boxed integer value""" @@ -167,6 +167,10 @@ def invariant(self): return isinstance(self.hash, int) + def become(self, w_other): + self.hash, w_other.hash = w_other.hash, self.hash + return True + class W_AbstractObjectWithClassReference(W_AbstractObjectWithIdentityHash): """Objects with arbitrary class (ie not CompiledMethod, SmallInteger or Float).""" @@ -193,12 +197,12 @@ return (W_AbstractObjectWithIdentityHash.invariant(self) and isinstance(self.w_class, W_PointersObject)) - def become(self, w_old, w_new): - # TODO to be eventually replaced by PyPy's become - if self.w_class == w_old: - self.w_class = w_new - elif self.w_class == w_new: - self.w_class = w_old + def become(self, w_other): + if not isinstance(w_other, W_AbstractObjectWithClassReference): + return False + self.w_class, w_other.w_class = w_other.w_class, self.w_class + return W_AbstractObjectWithIdentityHash.become(self, w_other) + class W_PointersObject(W_AbstractObjectWithClassReference): """Common object.""" @@ -294,14 +298,12 @@ from pypy.lang.smalltalk.shadow import MethodDictionaryShadow return self.as_special_get_shadow(MethodDictionaryShadow) - def become(self, w_old, w_new): - W_AbstractObjectWithClassReference.become(self, w_old, w_new) - for i in range(len(self._vars)): - w_test = self.fetch(i) - if w_test == w_old: - self.store(i, w_new) - elif w_test == w_new: - self.store(i, w_old) + def become(self, w_other): + if not isinstance(w_other, W_PointersObject): + return False + self._vars, w_other._vars = w_other._vars, self._vars + return W_AbstractObjectWithClassReference.become(self, w_other) + class W_BytesObject(W_AbstractObjectWithClassReference): def __init__(self, w_class, size): Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/objtable.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/objtable.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/objtable.py Mon May 19 12:14:40 2008 @@ -8,7 +8,7 @@ def wrap_char_table(): global w_charactertable def bld_char(i): - w_cinst = classtable.w_Character.as_class_get_shadow().new(store=False) + w_cinst = classtable.w_Character.as_class_get_shadow().new() w_cinst.store(constants.CHARACTER_VALUE_INDEX, model.W_SmallInteger(i)) return w_cinst @@ -18,8 +18,8 @@ wrap_char_table() -w_true = classtable.classtable['w_True'].as_class_get_shadow().new(store=False) -w_false = classtable.classtable['w_False'].as_class_get_shadow().new(store=False) +w_true = classtable.classtable['w_True'].as_class_get_shadow().new() +w_false = classtable.classtable['w_False'].as_class_get_shadow().new() w_minus_one = model.W_SmallInteger(-1) w_zero = model.W_SmallInteger(0) w_one = model.W_SmallInteger(1) @@ -32,8 +32,6 @@ w_nil.w_class = classtable.classtable['w_UndefinedObject'] objtable = {} -# XXX Used for non-PyPy way of doing become. -objects = [] for name in constants.objects_in_special_object_table: name = "w_" + name Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/primitives.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/primitives.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/primitives.py Mon May 19 12:14:40 2008 @@ -503,11 +503,9 @@ @expose_primitive(BECOME, unwrap_spec=[object, object]) def func(interp, w_rcvr, w_new): -# Non-PyPy way of doing become - for w_object in objtable.objects: - w_object.become(w_rcvr, w_new) - return w_rcvr - #raise PrimitiveNotYetWrittenError + if w_rcvr.become(w_new): + return w_rcvr + raise PrimitiveNotYetWrittenError def fake_bytes_left(): return utility.wrap_int(2**20) # XXX we don't know how to do this :-( Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py Mon May 19 12:14:40 2008 @@ -135,40 +135,44 @@ self.instance_kind = COMPILED_METHOD else: raise ClassShadowError("unknown format %d" % (format,)) - # read the name - if w_self.size() > constants.CLASS_NAME_INDEX: - w_name = w_self._vars[constants.CLASS_NAME_INDEX] - else: - w_name = None - # Some heuristic to find the classname - # Only used for debugging - # XXX This is highly experimental XXX - # if the name-pos of class is not bytesobject, - # we are probably holding a metaclass instead of a class. - # metaclasses hold a pointer to the real class in the last - # slot. This is pos 6 in mini.image and higher in squeak3.9 - if w_name is None: - w_realclass = w_self._vars[w_self.size() - 1] - assert isinstance(w_realclass, model.W_PointersObject) - if w_realclass.size() > constants.CLASS_NAME_INDEX: - w_name = w_realclass._vars[constants.CLASS_NAME_INDEX] - if isinstance(w_name, model.W_BytesObject): - self.name = w_name.as_string() + self.guess_class_name() + # read the methoddict self.w_methoddict = w_self._vars[constants.CLASS_METHODDICT_INDEX] assert isinstance(self.w_methoddict, model.W_PointersObject) + w_superclass = w_self._vars[constants.CLASS_SUPERCLASS_INDEX] if w_superclass is objtable.w_nil: self.w_superclass = None else: self.w_superclass = w_superclass + AbstractShadow.update_shadow(self) - # XXX check better way to store objects - # XXX storing is necessary for "become" which loops over all pointers - # XXX and replaces old pointers with new pointers - def new(self, extrasize=0, store=True): + def guess_class_name(self): + w_self = self.w_self() + + # read the name + if w_self.size() > constants.CLASS_NAME_INDEX: + w_name = w_self._vars[constants.CLASS_NAME_INDEX] + else: + # Some heuristic to find the classname + # Only used for debugging + # XXX This is highly experimental XXX + # if the name-pos of class is not bytesobject, + # we are probably holding a metaclass instead of a class. + # metaclasses hold a pointer to the real class in the last + # slot. This is pos 6 in mini.image and higher in squeak3.9 + w_realclass = w_self._vars[w_self.size() - 1] + assert isinstance(w_realclass, model.W_PointersObject) + if w_realclass.size() > constants.CLASS_NAME_INDEX: + w_name = w_realclass._vars[constants.CLASS_NAME_INDEX] + + if isinstance(w_name, model.W_BytesObject): + self.name = w_name.as_string() + + def new(self, extrasize=0): from pypy.lang.smalltalk import classtable w_cls = self.w_self() if self.instance_kind == POINTERS: @@ -181,10 +185,6 @@ w_new = model.W_CompiledMethod(extrasize) else: raise NotImplementedError(self.instance_kind) - # XXX Used for non-PyPy way of doing become. - if store: - from pypy.lang.smalltalk import objtable - objtable.objects.extend([w_new]) return w_new def s_methoddict(self): Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/squeakimage.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/squeakimage.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/squeakimage.py Mon May 19 12:14:40 2008 @@ -203,10 +203,6 @@ .g_object.pointers] from pypy.lang.smalltalk import objtable - # XXX Used for non-PyPy way of doing become. - objtable.objects.extend( - [chunk.g_object.w_object - for chunk in reader.chunklist]) for name, idx in constants.objects_in_special_object_table.items(): objtable.objtable["w_" + name] = self.special_objects[idx] Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_model.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_model.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_model.py Mon May 19 12:14:40 2008 @@ -163,3 +163,27 @@ test_not_equals(utility.wrap_char('a'), utility.wrap_char('d')) test_not_equals(utility.wrap_char('d'), utility.wrap_int(3)) test_not_equals(utility.wrap_char('d'), utility.wrap_float(3.0)) + +def test_become_pointers(): + w_clsa = mockclass(3) + w_a = w_clsa.as_class_get_shadow().new() + + w_clsb = mockclass(4) + w_b = w_clsb.as_class_get_shadow().new() + + hasha = w_a.gethash() + hashb = w_b.gethash() + + w_a.store(0, w_b) + w_b.store(1, w_a) + + res = w_a.become(w_b) + assert res + assert w_a.gethash() == hashb + assert w_b.gethash() == hasha + + assert w_a.getclass() is w_clsb + assert w_b.getclass() is w_clsa + + assert w_b.fetch(0) is w_b + assert w_a.fetch(1) is w_a From tverwaes at codespeak.net Mon May 19 12:36:19 2008 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Mon, 19 May 2008 12:36:19 +0200 (CEST) Subject: [pypy-svn] r54923 - in pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk: . test Message-ID: <20080519103619.47804168528@codespeak.net> Author: tverwaes Date: Mon May 19 12:36:17 2008 New Revision: 54923 Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/primitives.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_model.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/utility.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/wrapper.py Log: (cfbolz, tverwaes) rename equals to is_same_object and use instead of "is" Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py Mon May 19 12:36:17 2008 @@ -87,7 +87,7 @@ """Return internal representation of Squeak class.""" return self.getclass().as_class_get_shadow() - def equals(self, other): + def is_same_object(self, other): """Compare object identity""" return self is other @@ -118,7 +118,7 @@ def __repr__(self): return "W_SmallInteger(%d)" % self.value - def equals(self, other): + def is_same_object(self, other): # TODO what is correct terminology to say that identity is by value? if not isinstance(other, W_SmallInteger): return False @@ -143,7 +143,7 @@ def __repr__(self): return "W_Float(%f)" % self.value - def equals(self, other): + def is_same_object(self, other): if not isinstance(other, W_Float): return False # TODO is that correct in Squeak? @@ -345,7 +345,7 @@ return False return True - def equals(self, other): + def is_same_object(self, other): if not isinstance(other, W_BytesObject): return False return self.bytes == other.bytes Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/primitives.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/primitives.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/primitives.py Mon May 19 12:36:17 2008 @@ -449,7 +449,7 @@ @expose_primitive(EQUIVALENT, unwrap_spec=[object, object]) def func(interp, w_arg, w_rcvr): - return utility.wrap_bool(w_arg.equals(w_rcvr)) + return utility.wrap_bool(w_arg.is_same_object(w_rcvr)) @expose_primitive(CLASS, unwrap_spec=[object]) def func(interp, w_obj): Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py Mon May 19 12:36:17 2008 @@ -143,7 +143,7 @@ assert isinstance(self.w_methoddict, model.W_PointersObject) w_superclass = w_self._vars[constants.CLASS_SUPERCLASS_INDEX] - if w_superclass is objtable.w_nil: + if w_superclass.is_same_object(objtable.w_nil): self.w_superclass = None else: self.w_superclass = w_superclass @@ -279,7 +279,7 @@ self.methoddict = {} for i in range(size): w_selector = self.w_self()._vars[constants.METHODDICT_NAMES_INDEX+i] - if w_selector is not objtable.w_nil: + if not w_selector.is_same_object(objtable.w_nil): if not isinstance(w_selector, model.W_BytesObject): raise ClassShadowError("bogus selector in method dict") selector = w_selector.as_string() Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_model.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_model.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_model.py Mon May 19 12:36:17 2008 @@ -128,41 +128,41 @@ assert utility.unwrap_int(w_method.at0(13)) == ord('b') assert utility.unwrap_int(w_method.at0(14)) == ord('c') -def test_equals(w_o1=model.W_PointersObject(None,0), w_o2=None): +def test_is_same_object(w_o1=model.W_PointersObject(None,0), w_o2=None): if w_o2 is None: w_o2 = w_o1 - assert w_o1.equals(w_o2) - assert w_o2.equals(w_o1) + assert w_o1.is_same_object(w_o2) + assert w_o2.is_same_object(w_o1) -def test_not_equals(w_o1=model.W_PointersObject(None,0),w_o2=model.W_PointersObject(None,0)): - assert not w_o1.equals(w_o2) - assert not w_o2.equals(w_o1) +def test_not_is_same_object(w_o1=model.W_PointersObject(None,0),w_o2=model.W_PointersObject(None,0)): + assert not w_o1.is_same_object(w_o2) + assert not w_o2.is_same_object(w_o1) w_o2 = model.W_SmallInteger(2) - assert not w_o1.equals(w_o2) - assert not w_o2.equals(w_o1) + assert not w_o1.is_same_object(w_o2) + assert not w_o2.is_same_object(w_o1) w_o2 = model.W_Float(5.5) - assert not w_o1.equals(w_o2) - assert not w_o2.equals(w_o1) + assert not w_o1.is_same_object(w_o2) + assert not w_o2.is_same_object(w_o1) -def test_intfloat_equals(): - test_equals(model.W_SmallInteger(1), model.W_SmallInteger(1)) - test_equals(model.W_SmallInteger(100), model.W_SmallInteger(100)) - test_equals(model.W_Float(1.100), model.W_Float(1.100)) - -def test_intfloat_notequals(): - test_not_equals(model.W_SmallInteger(1), model.W_Float(1)) - test_not_equals(model.W_Float(100), model.W_SmallInteger(100)) - test_not_equals(model.W_Float(1.100), model.W_Float(1.200)) - test_not_equals(model.W_SmallInteger(101), model.W_SmallInteger(100)) - -def test_charequals(): - test_equals(utility.wrap_char('a'), utility.wrap_char('a')) - test_equals(utility.wrap_char('d'), utility.wrap_char('d')) - -def test_not_charequals(): - test_not_equals(utility.wrap_char('a'), utility.wrap_char('d')) - test_not_equals(utility.wrap_char('d'), utility.wrap_int(3)) - test_not_equals(utility.wrap_char('d'), utility.wrap_float(3.0)) +def test_intfloat_is_same_object(): + test_is_same_object(model.W_SmallInteger(1), model.W_SmallInteger(1)) + test_is_same_object(model.W_SmallInteger(100), model.W_SmallInteger(100)) + test_is_same_object(model.W_Float(1.100), model.W_Float(1.100)) + +def test_intfloat_notis_same_object(): + test_not_is_same_object(model.W_SmallInteger(1), model.W_Float(1)) + test_not_is_same_object(model.W_Float(100), model.W_SmallInteger(100)) + test_not_is_same_object(model.W_Float(1.100), model.W_Float(1.200)) + test_not_is_same_object(model.W_SmallInteger(101), model.W_SmallInteger(100)) + +def test_charis_same_object(): + test_is_same_object(utility.wrap_char('a'), utility.wrap_char('a')) + test_is_same_object(utility.wrap_char('d'), utility.wrap_char('d')) + +def test_not_charis_same_object(): + test_not_is_same_object(utility.wrap_char('a'), utility.wrap_char('d')) + test_not_is_same_object(utility.wrap_char('d'), utility.wrap_int(3)) + test_not_is_same_object(utility.wrap_char('d'), utility.wrap_float(3.0)) def test_become_pointers(): w_clsa = mockclass(3) Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/utility.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/utility.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/utility.py Mon May 19 12:36:17 2008 @@ -13,11 +13,11 @@ def unwrap_char(w_char): from pypy.lang.smalltalk import classtable, objtable, constants w_class = w_char.getclass() - if w_class is not classtable.w_Character: + if not w_class.is_same_object(classtable.w_Character): raise UnwrappingError("expected character, got %s" % (w_class, )) w_ord = w_char.fetch(constants.CHARACTER_VALUE_INDEX) w_class = w_ord.getclass() - if w_class is not classtable.w_SmallInteger: + if not w_class.is_same_object(classtable.w_SmallInteger): raise UnwrappingError("expected smallint from character, got %s" % (w_class, )) assert isinstance(w_ord, model.W_SmallInteger) Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/wrapper.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/wrapper.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/wrapper.py Mon May 19 12:36:17 2008 @@ -74,7 +74,7 @@ self.put_to_sleep() def is_active_process(self): - return self.w_self is scheduler().active_process() + return self.w_self.is_same_object(scheduler().active_process()) def suspend(self, interp): if self.is_active_process(): @@ -104,7 +104,7 @@ from pypy.lang.smalltalk import objtable w_first = self.first_link() w_last = self.last_link() - if w_first is w_last: + if w_first.is_same_object(w_last): self.store_first_link(objtable.w_nil) self.store_last_link(objtable.w_nil) else: @@ -120,12 +120,12 @@ else: current = LinkWrapper(self.first_link()) w_next = current.next_link() - while w_next is not objtable.w_nil: - if w_next is w_link: + while not w_next.is_same_object(objtable.w_nil): + if w_next.is_same_object(w_link): LinkWrapper(w_link).store_next_link(objtable.w_nil) w_tail = LinkWrapper(w_next).next_link() current.store_next_link(w_tail) - if w_tail is objtable.w_nil: + if w_tail.is_same_object(objtable.w_nil): self.store_last_link(current.w_self) return current = LinkWrapper(w_next) From tverwaes at codespeak.net Mon May 19 12:46:59 2008 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Mon, 19 May 2008 12:46:59 +0200 (CEST) Subject: [pypy-svn] r54924 - in pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk: . test Message-ID: <20080519104659.D4953169E30@codespeak.net> Author: tverwaes Date: Mon May 19 12:46:58 2008 New Revision: 54924 Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/primitives.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_miniimage.py Log: (cfbolz, tverwaes) replacing more == and != with is_same_object(cfbolz, tverwaes) replacing more == and != with is_same_object(cfbolz, tverwaes) replacing more == and != with is_same_object(cfbolz, tverwaes) replacing more == and != with is_same_object(cfbolz, tverwaes) replacing more == and != with is_same_object(cfbolz, tverwaes) replacing more == and != with is_same_object(cfbolz, tverwaes) replacing more == and != with is_same_object(cfbolz, tverwaes) replacing more == and != with is_same_object(cfbolz, tverwaes) replacing more == and != with is_same_object Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/primitives.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/primitives.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/primitives.py Mon May 19 12:46:58 2008 @@ -476,8 +476,8 @@ # 1. Rcvr or arg are SmallIntegers # XXX this is wrong too - if (w_arg_class == classtable.w_SmallInteger or - w_rcvr_class == classtable.w_SmallInteger): + if (w_arg_class.is_same_object(classtable.w_SmallInteger) or + w_rcvr_class.is_same_object(classtable.w_SmallInteger)): raise PrimitiveFailedError() # 2. Rcvr is an instance of a compact class and argument isn't @@ -662,7 +662,7 @@ w_block_ctx = frame.peek(argument_count) # XXX need to check this since VALUE is called on all sorts of objects. - if w_block_ctx.getclass() != classtable.w_BlockContext: + if not w_block_ctx.getclass().is_same_object(classtable.w_BlockContext): raise PrimitiveFailedError() assert isinstance(w_block_ctx, model.W_PointersObject) @@ -693,7 +693,7 @@ exp_arg_cnt = s_block_ctx.expected_argument_count() # Check that our arguments have pointers format and the right size: - if w_args.getclass() != classtable.w_Array: + if not w_args.getclass().is_same_object(classtable.w_Array): raise PrimitiveFailedError() if w_args.size() != exp_arg_cnt: raise PrimitiveFailedError() Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py Mon May 19 12:46:58 2008 @@ -347,7 +347,7 @@ def s_sender(self): from pypy.lang.smalltalk import objtable w_sender = self.w_sender() - if w_sender == objtable.w_nil: + if w_sender.is_same_object(objtable.w_nil): return None else: return w_sender.as_context_get_shadow() Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_miniimage.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_miniimage.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_miniimage.py Mon May 19 12:46:58 2008 @@ -252,7 +252,7 @@ ifTrue: [ 1 ] ifFalse: [ (self - 1) fib + (self - 2) fib ]""" perform(w(10).getclass(), "compile:classified:notifying:", w(sourcecode), w('pypy'), w(None)) - assert perform(w(10), "fib").equals(w(89)) + assert perform(w(10), "fib").is_same_object(w(89)) def w(any): if any is None: From afa at codespeak.net Mon May 19 13:31:50 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Mon, 19 May 2008 13:31:50 +0200 (CEST) Subject: [pypy-svn] r54925 - pypy/branch/win32port/pypy/translator/c/test Message-ID: <20080519113150.5BD6116853C@codespeak.net> Author: afa Date: Mon May 19 13:31:44 2008 New Revision: 54925 Modified: pypy/branch/win32port/pypy/translator/c/test/test_extfunc.py Log: Correct a test in a win32-only section of test_extfunc.py Modified: pypy/branch/win32port/pypy/translator/c/test/test_extfunc.py ============================================================================== --- pypy/branch/win32port/pypy/translator/c/test/test_extfunc.py (original) +++ pypy/branch/win32port/pypy/translator/c/test/test_extfunc.py Mon May 19 13:31:44 2008 @@ -657,9 +657,8 @@ elif hasattr(os, 'waitpid'): # windows has no fork but some waitpid to be emulated def test_waitpid(): + prog = str(sys.executable) def does_stuff(): - prog = sys.executable - prog = str(prog) args = [prog] # args = [prog, '-c', '"import os;os._exit(4)"'] # note that the above variant creates a bad array From afa at codespeak.net Mon May 19 14:08:34 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Mon, 19 May 2008 14:08:34 +0200 (CEST) Subject: [pypy-svn] r54926 - pypy/branch/win32port/pypy/translator/c/test Message-ID: <20080519120834.F2E78169E1E@codespeak.net> Author: afa Date: Mon May 19 14:08:33 2008 New Revision: 54926 Modified: pypy/branch/win32port/pypy/translator/c/test/test_newgc.py Log: Allow test_newgc to pass on win32 Modified: pypy/branch/win32port/pypy/translator/c/test/test_newgc.py ============================================================================== --- pypy/branch/win32port/pypy/translator/c/test/test_newgc.py (original) +++ pypy/branch/win32port/pypy/translator/c/test/test_newgc.py Mon May 19 14:08:33 2008 @@ -17,13 +17,14 @@ from pypy.config.pypyoption import get_pypy_config config = get_pypy_config(translating=True) config.translation.gc = gcpolicy + config.translation.countmallocs = True if t is None: t = TranslationContext(config=config) if inputtypes is not None: t.buildannotator().build_types(fn, inputtypes) t.buildrtyper().specialize() builder = genc.CExtModuleBuilder(t, fn, config=config) - builder.generate_source(defines={'COUNT_OP_MALLOCS': 1}) + builder.generate_source() builder.compile() if conftest.option.view: t.view() @@ -817,11 +818,13 @@ def test_callback_with_collect(self): from pypy.rlib.libffi import ffi_type_pointer, cast_type_to_ffitype,\ CDLL, ffi_type_void, CallbackFuncPtr, ffi_type_sint - from pypy.rpython.lltypesystem import rffi + from pypy.rpython.lltypesystem import rffi, ll2ctypes from pypy.rlib import rgc import gc slong = cast_type_to_ffitype(rffi.LONG) + libc_name = ll2ctypes.get_libc_name() + def callback(ll_args, ll_res, stuff): gc.collect() p_a1 = rffi.cast(rffi.VOIDPP, ll_args[0])[0] @@ -835,7 +838,7 @@ res[0] = -1 def f(): - libc = CDLL('libc.so.6') + libc = CDLL(libc_name) qsort = libc.getpointer('qsort', [ffi_type_pointer, slong, slong, ffi_type_pointer], ffi_type_void) From afa at codespeak.net Mon May 19 14:22:29 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Mon, 19 May 2008 14:22:29 +0200 (CEST) Subject: [pypy-svn] r54927 - pypy/branch/win32port/pypy/rpython/module/test Message-ID: <20080519122229.7FCEB16840D@codespeak.net> Author: afa Date: Mon May 19 14:22:22 2008 New Revision: 54927 Added: pypy/branch/win32port/pypy/rpython/module/test/test_ll_os_environ.py Log: A test for a previous correction Added: pypy/branch/win32port/pypy/rpython/module/test/test_ll_os_environ.py ============================================================================== --- (empty file) +++ pypy/branch/win32port/pypy/rpython/module/test/test_ll_os_environ.py Mon May 19 14:22:22 2008 @@ -0,0 +1,13 @@ +from pypy.translator.c.test.test_genc import compile +import os + +def test_environ_items(): + + def foo(x): + if x: + return len(os.environ.items()) + else: + return 0 + f = compile(foo, [int], backendopt=False) + assert f(1) > 0 + From afa at codespeak.net Mon May 19 14:28:28 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Mon, 19 May 2008 14:28:28 +0200 (CEST) Subject: [pypy-svn] r54928 - in pypy/branch/win32port/pypy/translator/c: . test Message-ID: <20080519122828.E4EDF16840D@codespeak.net> Author: afa Date: Mon May 19 14:28:27 2008 New Revision: 54928 Modified: pypy/branch/win32port/pypy/translator/c/genc.py pypy/branch/win32port/pypy/translator/c/test/test_standalone.py Log: Allow compilation of files residing outside the target directory. These files are copied into our working space, and compiled there. Used by libffi on win32. Modified: pypy/branch/win32port/pypy/translator/c/genc.py ============================================================================== --- pypy/branch/win32port/pypy/translator/c/genc.py (original) +++ pypy/branch/win32port/pypy/translator/c/genc.py Mon May 19 14:28:27 2008 @@ -304,8 +304,18 @@ if profopt is not None and not self.config.translation.noprofopt: profbased = (ProfOpt, profopt) + # Copy extrafiles to target directory, if needed + extrafiles = [] + for fn in self.extrafiles: + fn = py.path.local(fn) + if not fn.relto(udir): + newname = self.targetdir.join(fn.basename) + fn.copy(newname) + fn = newname + extrafiles.append(fn) + return CCompiler( - [self.c_source_filename] + self.extrafiles, + [self.c_source_filename] + extrafiles, self.eci, compiler_exe = cc, profbased = profbased) def compile(self): @@ -366,6 +376,8 @@ else: assert fn.dirpath().dirpath() == udir name = '../' + fn.relto(udir) + + name = name.replace("\\", "/") cfiles.append(name) if self.config.translation.gcrootfinder == "asmgcc": ofiles.append(name[:-2] + '.s') Modified: pypy/branch/win32port/pypy/translator/c/test/test_standalone.py ============================================================================== --- pypy/branch/win32port/pypy/translator/c/test/test_standalone.py (original) +++ pypy/branch/win32port/pypy/translator/c/test/test_standalone.py Mon May 19 14:28:27 2008 @@ -4,9 +4,10 @@ from pypy.rlib.rarithmetic import r_longlong from pypy.translator.translator import TranslationContext from pypy.translator.backendopt import all -from pypy.translator.c.genc import CStandaloneBuilder +from pypy.translator.c.genc import CStandaloneBuilder, ExternalCompilationInfo from pypy.annotation.listdef import s_list_of_strings from pypy.tool.udir import udir +from pypy.tool.autopath import pypydir def test_hello_world(): @@ -190,3 +191,42 @@ cbuilder.compile() data = cbuilder.cmdexec('hi there') assert data.strip() == "OK" + +def test_separate_files(): + # One file in translator/c/src + fname = py.path.local(pypydir).join( + 'translator', 'c', 'src', 'll_strtod.h') + + # One file in (another) subdir of the temp directory + dirname = udir.join("test_dir").ensure(dir=1) + fname2 = dirname.join("test_genc.c") + fname2.write(""" + void f() { + LL_strtod_formatd("%5f", 12.3); + }""") + + files = [fname, fname2] + + def entry_point(argv): + return 0 + + t = TranslationContext() + t.buildannotator().build_types(entry_point, [s_list_of_strings]) + t.buildrtyper().specialize() + + cbuilder = CStandaloneBuilder(t, entry_point, t.config) + cbuilder.eci = cbuilder.eci.merge( + ExternalCompilationInfo(separate_module_files=files)) + cbuilder.generate_source() + + makefile = udir.join(cbuilder.modulename, 'Makefile').read() + + # generated files are compiled in the same directory + assert " ../test_dir/test_genc.c" in makefile + assert " ../test_dir/test_genc.o" in makefile + + # but files from pypy source dir must be copied + assert "translator/c/src" not in makefile + assert " ll_strtod.h" in makefile + assert " ll_strtod.o" in makefile + From afa at codespeak.net Mon May 19 15:06:14 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Mon, 19 May 2008 15:06:14 +0200 (CEST) Subject: [pypy-svn] r54929 - in pypy/branch/win32port/pypy/translator/c: src test Message-ID: <20080519130614.682B3168437@codespeak.net> Author: afa Date: Mon May 19 15:06:11 2008 New Revision: 54929 Modified: pypy/branch/win32port/pypy/translator/c/src/instrument.h pypy/branch/win32port/pypy/translator/c/test/test_standalone.py Log: Instrumentation counters support on win32. test_prof_inline seems more difficult to adapt, though. Modified: pypy/branch/win32port/pypy/translator/c/src/instrument.h ============================================================================== --- pypy/branch/win32port/pypy/translator/c/src/instrument.h (original) +++ pypy/branch/win32port/pypy/translator/c/src/instrument.h Mon May 19 15:06:11 2008 @@ -9,10 +9,14 @@ #include #include #include +#ifndef WIN32 #include #include #include #include +#else +#include +#endif typedef unsigned long instrument_count_t; @@ -22,18 +26,33 @@ char *fname = getenv("_INSTRUMENT_COUNTERS"); if (fname) { int fd; +#ifdef WIN32 + HANDLE map_handle; + HANDLE file_handle; +#endif void *buf; size_t sz = sizeof(instrument_count_t)*INSTRUMENT_NCOUNTER; fd = open(fname, O_CREAT|O_TRUNC|O_RDWR, 0744); if (sz > 0) { lseek(fd, sz-1, SEEK_SET); write(fd, "", 1); +#ifndef WIN32 buf = mmap(NULL, sz, PROT_WRITE|PROT_READ, MAP_SHARED, fd, 0); if (buf == MAP_FAILED) { fprintf(stderr, "mapping instrument counters file failed\n"); abort(); } +#else + file_handle = (HANDLE)_get_osfhandle(fd); + map_handle = CreateFileMapping(file_handle, NULL, PAGE_READWRITE, + 0, sz, ""); + buf = MapViewOfFile(map_handle, FILE_MAP_WRITE, 0, 0, 0); + if (buf == 0) { + fprintf(stderr, "mapping instrument counters file failed\n"); + abort(); + } +#endif _instrument_counters = (instrument_count_t *)buf; } } Modified: pypy/branch/win32port/pypy/translator/c/test/test_standalone.py ============================================================================== --- pypy/branch/win32port/pypy/translator/c/test/test_standalone.py (original) +++ pypy/branch/win32port/pypy/translator/c/test/test_standalone.py Mon May 19 15:06:11 2008 @@ -55,8 +55,6 @@ # gives the strings unquoted in the list def test_counters(): - if sys.platform == 'win32': - py.test.skip("instrument counters support is unix only for now") from pypy.rpython.lltypesystem import lltype from pypy.rpython.lltypesystem.lloperation import llop def entry_point(argv): @@ -139,8 +137,6 @@ assert map(float, data.split()) == [0.0, 0.0] def test_profopt(): - if sys.platform == 'win32': - py.test.skip("instrumentation support is unix only for now") def add(a,b): return a + b - b + b - b + b - b + b - b + b - b + b - b + b def entry_point(argv): From arigo at codespeak.net Mon May 19 15:27:17 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 19 May 2008 15:27:17 +0200 (CEST) Subject: [pypy-svn] r54931 - in pypy/dist/pypy/translator: . goal tool tool/test Message-ID: <20080519132717.5BA7F2A017B@codespeak.net> Author: arigo Date: Mon May 19 15:27:15 2008 New Revision: 54931 Modified: pypy/dist/pypy/translator/driver.py pypy/dist/pypy/translator/goal/timing.py pypy/dist/pypy/translator/tool/cbuild.py pypy/dist/pypy/translator/tool/taskengine.py pypy/dist/pypy/translator/tool/test/test_taskengine.py Log: Check early if Boehm is installed or not when starting a translation. Modified: pypy/dist/pypy/translator/driver.py ============================================================================== --- pypy/dist/pypy/translator/driver.py (original) +++ pypy/dist/pypy/translator/driver.py Mon May 19 15:27:15 2008 @@ -32,12 +32,14 @@ } -def taskdef(taskfunc, deps, title, new_state=None, expected_states=[], idemp=False): +def taskdef(taskfunc, deps, title, new_state=None, expected_states=[], + idemp=False, earlycheck=None): taskfunc.task_deps = deps taskfunc.task_title = title taskfunc.task_newstate = None taskfunc.task_expected_states = expected_states taskfunc.task_idempotent = idemp + taskfunc.task_earlycheck = earlycheck return taskfunc # TODO: @@ -460,6 +462,16 @@ "inserting stack checks") STACKCHECKINSERTION = 'stackcheckinsertion_lltype' + def possibly_check_for_boehm(self): + if self.config.translation.gc == "boehm": + from pypy.translator.tool.cbuild import check_boehm_presence + from pypy.translator.tool.cbuild import CompilationError + try: + check_boehm_presence(noerr=False) + except CompilationError, e: + i = 'Boehm GC not installed. Try e.g. "translate.py --gc=hybrid"' + raise CompilationError('%s\n--------------------\n%s' % (e, i)) + def task_database_c(self): translator = self.translator if translator.annotator is not None: @@ -483,7 +495,8 @@ # task_database_c = taskdef(task_database_c, [STACKCHECKINSERTION, '?'+BACKENDOPT, RTYPE, '?annotate'], - "Creating database for generating c source") + "Creating database for generating c source", + earlycheck = possibly_check_for_boehm) def task_source_c(self): # xxx messy translator = self.translator @@ -828,6 +841,8 @@ # checkpointing support def _event(self, kind, goal, func): + if kind == 'planned' and func.task_earlycheck: + func.task_earlycheck(self) if kind == 'pre': fork_before = self.config.translation.fork_before if fork_before: Modified: pypy/dist/pypy/translator/goal/timing.py ============================================================================== --- pypy/dist/pypy/translator/goal/timing.py (original) +++ pypy/dist/pypy/translator/goal/timing.py Mon May 19 15:27:15 2008 @@ -31,7 +31,10 @@ self.tk = now def ttime(self): - return self.tk - self.t0 + try: + return self.tk - self.t0 + except AttributeError: + return 0.0 def pprint(self): """ Pretty print Modified: pypy/dist/pypy/translator/tool/cbuild.py ============================================================================== --- pypy/dist/pypy/translator/tool/cbuild.py (original) +++ pypy/dist/pypy/translator/tool/cbuild.py Mon May 19 15:27:15 2008 @@ -587,7 +587,7 @@ compiler.build(noerr=noerr) return str(compiler.outputfilename) -def check_boehm_presence(): +def check_boehm_presence(noerr=True): from pypy.tool.udir import udir try: cfile = udir.join('check_boehm.c') @@ -605,9 +605,12 @@ eci = ExternalCompilationInfo(libraries=['gc_pypy']) else: eci = ExternalCompilationInfo(libraries=['gc']) - build_executable([cfname], eci, noerr=True) + build_executable([cfname], eci, noerr=noerr) except CompilationError: - return False + if noerr: + return False + else: + raise else: return True Modified: pypy/dist/pypy/translator/tool/taskengine.py ============================================================================== --- pypy/dist/pypy/translator/tool/taskengine.py (original) +++ pypy/dist/pypy/translator/tool/taskengine.py Mon May 19 15:27:15 2008 @@ -105,7 +105,11 @@ def _execute(self, goals, *args, **kwds): task_skip = kwds.get('task_skip', []) res = None - for goal in self._plan(goals, skip=task_skip): + goals = self._plan(goals, skip=task_skip) + for goal in goals: + taskcallable, _ = self.tasks[goal] + self._event('planned', goal, taskcallable) + for goal in goals: taskcallable, _ = self.tasks[goal] self._event('pre', goal, taskcallable) try: Modified: pypy/dist/pypy/translator/tool/test/test_taskengine.py ============================================================================== --- pypy/dist/pypy/translator/tool/test/test_taskengine.py (original) +++ pypy/dist/pypy/translator/tool/test/test_taskengine.py Mon May 19 15:27:15 2008 @@ -86,6 +86,8 @@ def trace(goals): t = [] for goal in goals: + t.append(('planned', goal)) + for goal in goals: t.extend([('pre', goal), goal, ('post', goal)]) return t From tverwaes at codespeak.net Mon May 19 15:28:07 2008 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Mon, 19 May 2008 15:28:07 +0200 (CEST) Subject: [pypy-svn] r54932 - in pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk: . test Message-ID: <20080519132807.5BC182A017B@codespeak.net> Author: tverwaes Date: Mon May 19 15:28:06 2008 New Revision: 54932 Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/constants.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/objtable.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/squeakimage.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_primitives.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/wrapper.py Log: (cfbolz, tverwaes) moving from global object dictionary, since it's not necessarily consistent after translating Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/constants.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/constants.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/constants.py Mon May 19 15:28:06 2008 @@ -128,7 +128,6 @@ "false": SO_FALSE, "charactertable": SO_CHARACTER_TABLE_ARRAY, "schedulerassociationpointer" : SO_SCHEDULERASSOCIATIONPOINTER, - "compactclasses" : SO_COMPACT_CLASSES_ARRAY, "smalltalkdict" : SO_SMALLTALK, } Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/objtable.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/objtable.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/objtable.py Mon May 19 15:28:06 2008 @@ -31,11 +31,19 @@ w_nil = model.w_nil w_nil.w_class = classtable.classtable['w_UndefinedObject'] -objtable = {} +# We use indirection because translated globals are assumed to be constant +class ObjectTableHolder(object): + pass + +object_table_holder = ObjectTableHolder() +object_table_holder.objtable = {} + +def get_objtable(): + return object_table_holder.objtable for name in constants.objects_in_special_object_table: name = "w_" + name try: - objtable[name] = globals()[name] + get_objtable()[name] = globals()[name] except KeyError, e: - objtable[name] = None + get_objtable()[name] = None Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/squeakimage.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/squeakimage.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/squeakimage.py Mon May 19 15:28:06 2008 @@ -124,7 +124,7 @@ chunk.g_object.init_w_object() def assign_prebuilt_constants(self): - from pypy.lang.smalltalk import classtable, constants, objtable + from pypy.lang.smalltalk import classtable, constants # assign w_objects for objects that are already in classtable for name, so_index in constants.classes_in_special_object_table.items(): # w_object = getattr(classtable, "w_" + name) @@ -133,7 +133,7 @@ # assign w_objects for objects that are already in objtable for name, so_index in constants.objects_in_special_object_table.items(): # w_object = getattr(objtable, "w_" + name) - w_object = objtable.objtable["w_" + name] + w_object = objtable.get_objtable()["w_" + name] self.special_object(so_index).w_object = w_object def special_object(self, index): @@ -204,7 +204,7 @@ from pypy.lang.smalltalk import objtable for name, idx in constants.objects_in_special_object_table.items(): - objtable.objtable["w_" + name] = self.special_objects[idx] + objtable.get_objtable()["w_" + name] = self.special_objects[idx] def special(self, index): return self.special_objects[index] Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_primitives.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_primitives.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_primitives.py Mon May 19 15:28:06 2008 @@ -393,45 +393,6 @@ now = int(time.time()) assert (prim(primitives.SECONDS_CLOCK, [42]).value - now) <= 2 -def test_become(): - py.test.skip("implement me!") - """ - testBecome - | p1 p2 a | - p1 := 1 at 2. - p2 := #(3 4 5). - a := p1 -> p2. - XXX ? self assert: 1 at 2 = a key. - XXX ? self assert: #(3 4 5) = a value. - XXX ? self assert: p1 -> p2 = a. - self assert: p1 == a key. - self assert: p2 == a value. - p1 become: p2. - XXX ? self assert: 1 at 2 = a value. - XXX ? self assert: #(3 4 5) = a key. - XXX ? self assert: p1 -> p2 = a. - self assert: p1 == a key. - self assert: p2 == a value. - - self should: [1 become: 2] raise: Error. - """ - # XXX Test deviates from original spec - w_p1 = model.W_PointersObject(None, 2) - w_p2 = model.W_PointersObject(None, 3) - w_a = model.W_PointersObject(classtable.w_Array, 2) - w_a.atput0(0,w_p1) - w_a.atput0(1,w_p2) - objtable.objects += [w_p1] - objtable.objects += [w_p2] - objtable.objects += [w_a] - s_a = w_a.as_association_get_shadow() - assert s_a.key() == w_p1 - assert s_a.value() == w_p2 - prim(primitives.BECOME, [w_p1, w_p2]) - s_a = w_a.as_association_get_shadow() - assert s_a.key() == w_p2 - assert s_a.value() == w_p1 - def test_load_inst_var(): " try to test the LoadInstVar primitives a little " w_v = prim(primitives.INST_VAR_AT_0, ["q"]) Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/wrapper.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/wrapper.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/wrapper.py Mon May 19 15:28:06 2008 @@ -163,7 +163,7 @@ def scheduler(): from pypy.lang.smalltalk import objtable - w_association = objtable.objtable["w_schedulerassociationpointer"] + w_association = objtable.get_objtable()["w_schedulerassociationpointer"] assert w_association is not None w_scheduler = AssociationWrapper(w_association).value() assert isinstance(w_scheduler, model.W_PointersObject) From tverwaes at codespeak.net Mon May 19 15:35:08 2008 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Mon, 19 May 2008 15:35:08 +0200 (CEST) Subject: [pypy-svn] r54934 - in pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk: . test Message-ID: <20080519133508.4B2882A017B@codespeak.net> Author: tverwaes Date: Mon May 19 15:35:07 2008 New Revision: 54934 Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_model.py Log: (cfbolz, tverwaes) also swapping shadows in become of W_PointersObject Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py Mon May 19 15:35:07 2008 @@ -302,6 +302,7 @@ if not isinstance(w_other, W_PointersObject): return False self._vars, w_other._vars = w_other._vars, self._vars + self._shadow, w_other._shadow = w_other._shadow, self._shadow return W_AbstractObjectWithClassReference.become(self, w_other) Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py Mon May 19 15:35:07 2008 @@ -152,6 +152,7 @@ def guess_class_name(self): w_self = self.w_self() + w_name = None # read the name if w_self.size() > constants.CLASS_NAME_INDEX: Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_model.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_model.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_model.py Mon May 19 15:35:07 2008 @@ -187,3 +187,13 @@ assert w_b.fetch(0) is w_b assert w_a.fetch(1) is w_a + +def test_become_with_shadow(): + w_clsa = mockclass(3) + s_clsa = w_clsa.as_class_get_shadow() + w_clsb = mockclass(4) + s_clsb = w_clsb.as_class_get_shadow() + res = w_clsa.become(w_clsb) + assert res + assert w_clsa.as_class_get_shadow() is s_clsb + assert w_clsb.as_class_get_shadow() is s_clsa From tverwaes at codespeak.net Mon May 19 15:38:32 2008 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Mon, 19 May 2008 15:38:32 +0200 (CEST) Subject: [pypy-svn] r54935 - pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk Message-ID: <20080519133832.4138E2A0180@codespeak.net> Author: tverwaes Date: Mon May 19 15:38:26 2008 New Revision: 54935 Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py Log: (cfbolz, tverwaes) only get contextpart of already shadowed pointersobjects Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py Mon May 19 15:38:26 2008 @@ -292,6 +292,8 @@ def as_context_get_shadow(self, invalid=True): from pypy.lang.smalltalk.shadow import ContextPartShadow + # XXX TODO should figure out itself if its method or block context + assert self._shadow is not None return self.as_special_get_shadow(ContextPartShadow, invalid) def as_methoddict_get_shadow(self): From stephan at codespeak.net Mon May 19 15:55:02 2008 From: stephan at codespeak.net (stephan at codespeak.net) Date: Mon, 19 May 2008 15:55:02 +0200 (CEST) Subject: [pypy-svn] r54936 - in pypy/dist/pypy/rlib/rsdl: . test Message-ID: <20080519135502.D542716855C@codespeak.net> Author: stephan Date: Mon May 19 15:55:01 2008 New Revision: 54936 Modified: pypy/dist/pypy/rlib/rsdl/RSDL.py pypy/dist/pypy/rlib/rsdl/RSDL_helper.py pypy/dist/pypy/rlib/rsdl/test/test_video.py Log: added set_pixel and tests about it Modified: pypy/dist/pypy/rlib/rsdl/RSDL.py ============================================================================== --- pypy/dist/pypy/rlib/rsdl/RSDL.py (original) +++ pypy/dist/pypy/rlib/rsdl/RSDL.py Mon May 19 15:55:01 2008 @@ -201,3 +201,11 @@ ShowCursor = external('SDL_ShowCursor', [rffi.INT], rffi.INT) + +Delay = external('SDL_Delay', + [Uint32], + lltype.Void) + +UpdateRect = external('SDL_UpdateRect', + [SurfacePtr, rffi.INT, rffi.INT, rffi.INT], + lltype.Void) Modified: pypy/dist/pypy/rlib/rsdl/RSDL_helper.py ============================================================================== --- pypy/dist/pypy/rlib/rsdl/RSDL_helper.py (original) +++ pypy/dist/pypy/rlib/rsdl/RSDL_helper.py Mon May 19 15:55:01 2008 @@ -64,3 +64,34 @@ return p[0] else: raise ValueError("bad BytesPerPixel") + +def set_pixel(image, x, y, pixel): + """Return the pixel value at (x, y) + NOTE: The surface must be locked before calling this! + """ + bpp = rffi.getintfield(image.c_format, 'c_BytesPerPixel') + pitch = rffi.getintfield(image, 'c_pitch') + # Here p is the address to the pixel we want to retrieve + p = rffi.ptradd(image.c_pixels, y * pitch + x * bpp) + if bpp == 1: + p[0] = pixel + elif bpp == 2: + p = rffi.cast(RSDL.Uint16P, p) + p[0] = pixel + elif bpp == 3: + p = rffi.cast(lltype.Signed, p) + if RSDL.BYTEORDER == RSDL.BIG_ENDIAN: + p[0] = (pixel >> 16) & 0xFF + p[1] = (pixel >> 8 ) & 0xFF + p[2] = pixel & 0xFF + else: + p[0] = pixel & 0xFF + p[1] = (pixel >> 8 ) & 0xFF + p[2] = (pixel >> 16) & 0xFF + elif bpp == 4: + p = rffi.cast(RSDL.Uint32P, p) + p[0] = pixel + else: + raise ValueError("bad BytesPerPixel") + + Modified: pypy/dist/pypy/rlib/rsdl/test/test_video.py ============================================================================== --- pypy/dist/pypy/rlib/rsdl/test/test_video.py (original) +++ pypy/dist/pypy/rlib/rsdl/test/test_video.py Mon May 19 15:55:01 2008 @@ -1,6 +1,6 @@ import py, sys -from pypy.rlib.rsdl import RSDL +from pypy.rlib.rsdl import RSDL, RSDL_helper from pypy.rlib.rarithmetic import r_uint from pypy.rpython.lltypesystem import lltype, rffi from pypy import conftest @@ -159,6 +159,26 @@ RSDL.ShowCursor(RSDL.ENABLE) self.check("Is the cursor shown? ") + def test_bit_pattern(self): + HEIGHT = WIDTH = 10 + fmt = self.screen.c_format + white = RSDL.MapRGB(fmt, 255, 255, 255) + black = RSDL.MapRGB(fmt, 0, 0, 0) + RSDL.LockSurface(self.screen) + for i in xrange(WIDTH): + for j in xrange(HEIGHT): + k = j*WIDTH + i + if k % 2: + c = white + else: + c = black + + RSDL_helper.set_pixel(self.screen, i, j, c) +# + RSDL.UnlockSurface(self.screen) + RSDL.Flip(self.screen) + self.check("Upper left corner 10x10 field with vertical black/white stripes") + def test_blit_rect(self): surface = RSDL.CreateRGBSurface(0, 150, 50, 32, r_uint(0x000000FF), @@ -187,6 +207,7 @@ RSDL.Flip(self.screen) finally: lltype.free(dstrect, flavor='raw') + lltype.free(paintrect, flavor='raw') RSDL.FreeSurface(surface) self.check("Half Red/Orange rectangle(150px * 50px) at the top left, 10 pixels from the border") From cami at codespeak.net Mon May 19 15:57:15 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Mon, 19 May 2008 15:57:15 +0200 (CEST) Subject: [pypy-svn] r54937 - in pypy/dist/pypy/rlib/rsdl: . test Message-ID: <20080519135715.5475A168443@codespeak.net> Author: cami Date: Mon May 19 15:57:12 2008 New Revision: 54937 Modified: pypy/dist/pypy/rlib/rsdl/constants.py pypy/dist/pypy/rlib/rsdl/test/test_video.py Log: merged files Modified: pypy/dist/pypy/rlib/rsdl/constants.py ============================================================================== --- pypy/dist/pypy/rlib/rsdl/constants.py (original) +++ pypy/dist/pypy/rlib/rsdl/constants.py Mon May 19 15:57:12 2008 @@ -49,9 +49,10 @@ "MOUSEBUTTONDOWN", "MOUSEBUTTONUP", "BUTTON_LEFT", - "BUTTON_LEFT", "BUTTON_MIDDLE", "BUTTON_RIGHT", + "BUTTON_WHEELUP", + "BUTTON_WHEELDOWN", "JOYAXISMOTION", "JOYBALLMOTION", "JOYHATMOTION", Modified: pypy/dist/pypy/rlib/rsdl/test/test_video.py ============================================================================== --- pypy/dist/pypy/rlib/rsdl/test/test_video.py (original) +++ pypy/dist/pypy/rlib/rsdl/test/test_video.py Mon May 19 15:57:12 2008 @@ -111,10 +111,8 @@ finally: lltype.free(event, flavor='raw') - - - def test_mousebutton(self): + def test_mousebutton_wheel(self): if not self.is_interactive: py.test.skip("interactive test only") print @@ -123,7 +121,9 @@ event_tests = [("left button", RSDL.BUTTON_LEFT), ("middle button", RSDL.BUTTON_MIDDLE), - ("right button", RSDL.BUTTON_RIGHT)] + ("right button", RSDL.BUTTON_RIGHT), + ("scroll up", RSDL.BUTTON_WHEELUP), + ("scroll down", RSDL.BUTTON_WHEELDOWN)] test_success = [] event = lltype.malloc(RSDL.Event, flavor='raw') try: @@ -152,7 +152,45 @@ finally: lltype.free(event, flavor='raw') + def test_mousewheel(self): + if not self.is_interactive: + py.test.skip("interactive test only") + print + print "Press the given MouseButtons:" + print " Use Escape to quit." + event_tests = [("scroll up", RSDL.BUTTON_WHEELUP), + ("scroll down", RSDL.BUTTON_WHEELDOWN)] + test_success = [] + event = lltype.malloc(RSDL.Event, flavor='raw') + try: + for button_test in event_tests: + print " press %s:" % button_test[0] + while True: + ok = RSDL.WaitEvent(event) + assert rffi.cast(lltype.Signed, ok) == 1 + c_type = rffi.getintfield(event, 'c_type') + if c_type == RSDL.MOUSEBUTTONDOWN: + b = rffi.cast(RSDL.MouseButtonEventPtr, event) + print "down", rffi.getintfield(b, "c_x"), \ + rffi.getintfield(b, "c_y") + elif c_type == RSDL.MOUSEBUTTONUP: + b = rffi.cast(RSDL.MouseButtonEventPtr, event) + print "up", rffi.getintfield(b, "c_x"), \ + rffi.getintfield(b, "c_y") + elif c_type == RSDL.KEYUP: + p = rffi.cast(RSDL.KeyboardEventPtr, event) + if rffi.getintfield(p.c_keysym, 'c_sym') == RSDL.K_ESCAPE: + test_success.append(False) + print " manually aborted" + break + #break + if False in test_success: + py.test.fail("") + finally: + lltype.free(event, flavor='raw') + + def test_show_hide_cursor(self): RSDL.ShowCursor(RSDL.DISABLE) self.check("Is the cursor hidden? ") @@ -174,7 +212,6 @@ c = black RSDL_helper.set_pixel(self.screen, i, j, c) -# RSDL.UnlockSurface(self.screen) RSDL.Flip(self.screen) self.check("Upper left corner 10x10 field with vertical black/white stripes") From afa at codespeak.net Mon May 19 15:58:59 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Mon, 19 May 2008 15:58:59 +0200 (CEST) Subject: [pypy-svn] r54938 - pypy/branch/win32port/pypy/config Message-ID: <20080519135859.4A58B16843D@codespeak.net> Author: afa Date: Mon May 19 15:58:56 2008 New Revision: 54938 Modified: pypy/branch/win32port/pypy/config/pypyoption.py Log: _rawffi is not a working_module on win32. Note that translation fails when inlining is disabled (--no-translation-backendopt-inline): An invalid empty structure is generated around the function _rawffi.structure.cast_pos, when specialized for ll_t=Void. And I suspect this happens on Unix as well. Modified: pypy/branch/win32port/pypy/config/pypyoption.py ============================================================================== --- pypy/branch/win32port/pypy/config/pypyoption.py (original) +++ pypy/branch/win32port/pypy/config/pypyoption.py Mon May 19 15:58:56 2008 @@ -37,8 +37,6 @@ del working_modules["_minimal_curses"] # modules currently missing explicit windows support del working_modules["signal"] - del working_modules["_rawffi"] - module_dependencies = {} From cami at codespeak.net Mon May 19 16:18:45 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Mon, 19 May 2008 16:18:45 +0200 (CEST) Subject: [pypy-svn] r54940 - pypy/dist/pypy/translator/goal Message-ID: <20080519141845.7F47E1684E1@codespeak.net> Author: cami Date: Mon May 19 16:18:42 2008 New Revision: 54940 Added: pypy/dist/pypy/translator/goal/targetsimplevideo.py Log: created simple videotest Added: pypy/dist/pypy/translator/goal/targetsimplevideo.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/goal/targetsimplevideo.py Mon May 19 16:18:42 2008 @@ -0,0 +1,92 @@ +from pypy.rlib.rsdl import RSDL, RSDL_helper +from pypy.rpython.lltypesystem import rffi, lltype +import py + +WIDTH = 200 +HEIGHT = 200 + +def entry_point(argv=None): + RSDL.Init(RSDL.INIT_VIDEO) >= 0 + screen = RSDL.SetVideoMode(WIDTH, HEIGHT, 32, 0) + event = lltype.malloc(RSDL.Event, flavor='raw') + try: + while True: + ok = RSDL.WaitEvent(event) + assert rffi.cast(lltype.Signed, ok) == 1 + c_type = rffi.getintfield(event, 'c_type') + if c_type == RSDL.KEYDOWN: + p = rffi.cast(RSDL.KeyboardEventPtr, event) + if rffi.getintfield(p.c_keysym, 'c_sym') == RSDL.K_ESCAPE: + print 'Escape key' + break + update_screen(screen) + finally: + lltype.free(event, flavor='raw') + +# ----------------------------------------------------------------------------- + +def chess(screen, cola, colb): + for i in xrange(WIDTH): + for j in xrange(HEIGHT): + if (i+j) % 2: + c = cola + else: + c = colb + RSDL_helper.set_pixel(screen, i, j, c) + +def white(screen, cola, colb): + for i in xrange(WIDTH): + for j in xrange(HEIGHT): + RSDL_helper.set_pixel(screen, i, j, colb) + +def black(screen, cola, colb): + for i in xrange(WIDTH): + for j in xrange(HEIGHT): + RSDL_helper.set_pixel(screen, i, j, cola) + +def stripes_v(screen, cola, colb): + for i in xrange(WIDTH): + for j in xrange(HEIGHT): + k = j*WIDTH + i + if k % 2: + c = cola + else: + c = colb + RSDL_helper.set_pixel(screen, i, j, c) + +def stripes_m(screen, cola, colb): + for j in xrange(WIDTH): + for i in xrange(HEIGHT): + k = j*WIDTH + i + if k % 2: + c = cola + else: + c = colb + RSDL_helper.set_pixel(screen, i, j, c) + + +# ----------------------------------------------------------------------------- + +pattern = (chess, white, black, stripes_v, stripes_m) +current_pattern_id = 0 +def update_screen(screen): + fmt = self.screen.c_format + white = RSDL.MapRGB(fmt, 255, 255, 255) + black = RSDL.MapRGB(fmt, 0, 0, 0) + RSDL.LockSurface(self.screen) + pattern[current_pattern_id % len(pattern)](screen, black, white) + RSDL.UnlockSurface(self.screen) + RSDL.Flip(self.screen) + current_pattern_id += 1 + + +# ----------------------------------------------------------------------------- + +def target(*args): + return entry_point, None + + +if __name__ == '__main__': + entry_point() + + From antocuni at codespeak.net Mon May 19 16:48:03 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 19 May 2008 16:48:03 +0200 (CEST) Subject: [pypy-svn] r54942 - pypy/django/tests Message-ID: <20080519144803.C14AE168545@codespeak.net> Author: antocuni Date: Mon May 19 16:47:58 2008 New Revision: 54942 Modified: pypy/django/tests/conftest.py Log: (antocuni, fijal, pedronis around) (IN-PROGRESS) conftest.py for django Modified: pypy/django/tests/conftest.py ============================================================================== --- pypy/django/tests/conftest.py (original) +++ pypy/django/tests/conftest.py Mon May 19 16:47:58 2008 @@ -8,7 +8,47 @@ DIRNAMES = ['modeltests', 'regressiontests']#, 'django/contrib'] +import py.__.test.compat +import unittest +unittest.TestCase = py.__.test.compat.TestCase + +class DocTestItem(py.test.collect.Item): + + def __init__(self, name, mod, docstr): + py.test.collect.Item.__init__(self, name) + self.docstr = docstr + self.mod = mod + + def run(self): + from django.test.utils import setup_test_environment, teardown_test_environment + from django.test.utils import create_test_db, destroy_test_db + from django.conf import settings + old_name = settings.DATABASE_NAME + setup_test_environment() + create_test_db(0) + try: + self.execute(self.mod, self.docstr) + finally: + destroy_test_db(old_name, 0) + teardown_test_environment() + + def execute(self, mod, docstring): + from django.test.testcases import OutputChecker, DocTestRunner + from django.test import _doctest + checker = OutputChecker() + runner = DocTestRunner(checker=checker) + finder = _doctest.DocTestFinder() + for test in finder.find(mod): + runner.run(test) + if runner.failures: + py.test.fail("doctest %s: %s failed out of %s" %( + self.fspath, runner.failures, runner.tries)) + + +loaded_apps = {} + class Directory(py.test.collect.Directory): + def run(self): rel = self.fspath.relto(rootdir) if not rel: @@ -23,7 +63,28 @@ return self.run2() def run2(self): + from django.conf import settings + from django.db.models.loading import load_app + from django.test.simple import build_suite + rel = self.fspath.relto(rootdir) + app_name = rel.replace(os.path.sep, '.') + if app_name in loaded_apps: + mod = loaded_apps[app_name] + else: + mod = load_app(app_name) + loaded_apps[app_name] = mod + if mod: + if app_name not in settings.INSTALLED_APPS: + settings.INSTALLED_APPS.append(app_name) + + if hasattr(mod, '__test__') and mod.__test__.get('API_TESTS'): + return [DocTestItem(self.fspath.basename + '.docstring', mod, mod.__test__['API_TESTS'])] return [] + #suite = build_suite(mod) + #x = suite._tests[1]._tests[0] + #return [x] + #return suite._tests + # modify the global settings def run1(self): models = [] @@ -39,10 +100,54 @@ def run0(self): return DIRNAMES - def join(self, name): + def join(self, name_or_item): + if isinstance(name_or_item, py.test.collect.Item): + return name_or_item + name = name_or_item path = self.fspath.join(name) if path.check(dir=1): return Directory(self.fspath.join(name)) else: - explode - + raise NotImplementedError + +ALWAYS_INSTALLED_APPS = [ + 'django.contrib.contenttypes', + 'django.contrib.auth', + 'django.contrib.sites', + 'django.contrib.flatpages', + 'django.contrib.redirects', + 'django.contrib.sessions', + 'django.contrib.comments', + 'django.contrib.admin', +] + +TEST_TEMPLATE_DIR = 'templates' + +def setup(): + import sys + sys.path.insert(0, str(rootdir)) + os.environ['DJANGO_SETTINGS_MODULE'] = 'settings' + + from django.conf import settings + + # Redirect some settings for the duration of these tests. + settings.INSTALLED_APPS = ALWAYS_INSTALLED_APPS + settings.ROOT_URLCONF = 'urls' + settings.TEMPLATE_DIRS = (os.path.join(os.path.dirname(__file__), TEST_TEMPLATE_DIR),) + settings.USE_I18N = True + settings.LANGUAGE_CODE = 'en' + settings.LOGIN_URL = '/accounts/login/' + settings.MIDDLEWARE_CLASSES = ( + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.middleware.common.CommonMiddleware', + ) + settings.SITE_ID = 1 + + # Load all the ALWAYS_INSTALLED_APPS. + # (This import statement is intentionally delayed until after we + # access settings because of the USE_I18N dependency.) + from django.db.models.loading import get_apps, load_app + get_apps() + +setup() From afa at codespeak.net Mon May 19 16:57:55 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Mon, 19 May 2008 16:57:55 +0200 (CEST) Subject: [pypy-svn] r54943 - pypy/dist/pypy/rpython/tool Message-ID: <20080519145755.6153E16857A@codespeak.net> Author: afa Date: Mon May 19 16:57:43 2008 New Revision: 54943 Modified: pypy/dist/pypy/rpython/tool/rffi_platform.py Log: Revert r54758, which breaks tests in module/thread (at least). Let's do this differently in the win32port branch. Modified: pypy/dist/pypy/rpython/tool/rffi_platform.py ============================================================================== --- pypy/dist/pypy/rpython/tool/rffi_platform.py (original) +++ pypy/dist/pypy/rpython/tool/rffi_platform.py Mon May 19 16:57:43 2008 @@ -537,9 +537,7 @@ """ def run_example_code(filepath, eci): - eci = eci.convert_sources_to_files() - files = [filepath] + list(eci.separate_module_files) - output = build_executable_cache(files, eci) + output = build_executable_cache([filepath], eci) section = None for line in output.splitlines(): line = line.strip() From stephan at codespeak.net Mon May 19 17:00:15 2008 From: stephan at codespeak.net (stephan at codespeak.net) Date: Mon, 19 May 2008 17:00:15 +0200 (CEST) Subject: [pypy-svn] r54944 - pypy/dist/pypy/rlib/rsdl Message-ID: <20080519150015.8EFEE16857A@codespeak.net> Author: stephan Date: Mon May 19 17:00:13 2008 New Revision: 54944 Modified: pypy/dist/pypy/rlib/rsdl/RSDL.py pypy/dist/pypy/rlib/rsdl/RSDL_helper.py Log: fixed set_pixel (cami, stephan) Modified: pypy/dist/pypy/rlib/rsdl/RSDL.py ============================================================================== --- pypy/dist/pypy/rlib/rsdl/RSDL.py (original) +++ pypy/dist/pypy/rlib/rsdl/RSDL.py Mon May 19 17:00:13 2008 @@ -122,9 +122,9 @@ # ------------------------------------------------------------------------------ def Init(flags): - if sys.platform == 'darwin': - from AppKit import NSApplication - NSApplication.sharedApplication() +# if sys.platform == 'darwin': +# from AppKit import NSApplication +# NSApplication.sharedApplication() return _Init(flags) # ------------------------------------------------------------------------------ Modified: pypy/dist/pypy/rlib/rsdl/RSDL_helper.py ============================================================================== --- pypy/dist/pypy/rlib/rsdl/RSDL_helper.py (original) +++ pypy/dist/pypy/rlib/rsdl/RSDL_helper.py Mon May 19 17:00:13 2008 @@ -74,23 +74,22 @@ # Here p is the address to the pixel we want to retrieve p = rffi.ptradd(image.c_pixels, y * pitch + x * bpp) if bpp == 1: - p[0] = pixel + p[0] = rffi.cast(rffi.UCHAR,pixel) elif bpp == 2: p = rffi.cast(RSDL.Uint16P, p) - p[0] = pixel + p[0] = rffi.cast(RSDL.Uint16,pixel) elif bpp == 3: - p = rffi.cast(lltype.Signed, p) if RSDL.BYTEORDER == RSDL.BIG_ENDIAN: - p[0] = (pixel >> 16) & 0xFF - p[1] = (pixel >> 8 ) & 0xFF - p[2] = pixel & 0xFF + p[0] = rffi.cast(rffi.UCHAR,(pixel >> 16) & 0xFF) + p[1] = rffi.cast(rffi.UCHAR,(pixel >> 8 ) & 0xFF) + p[2] = rffi.cast(rffi.UCHAR,pixel & 0xFF) else: - p[0] = pixel & 0xFF - p[1] = (pixel >> 8 ) & 0xFF - p[2] = (pixel >> 16) & 0xFF + p[0] = rffi.cast(rffi.UCHAR,pixel & 0xFF) + p[1] = rffi.cast(rffi.UCHAR,(pixel >> 8 ) & 0xFF) + p[2] = rffi.cast(rffi.UCHAR,(pixel >> 16) & 0xFF) elif bpp == 4: p = rffi.cast(RSDL.Uint32P, p) - p[0] = pixel + p[0] = rffi.cast(RSDL.Uint32, pixel) else: raise ValueError("bad BytesPerPixel") From stephan at codespeak.net Mon May 19 17:00:57 2008 From: stephan at codespeak.net (stephan at codespeak.net) Date: Mon, 19 May 2008 17:00:57 +0200 (CEST) Subject: [pypy-svn] r54945 - pypy/dist/pypy/translator/goal Message-ID: <20080519150057.2F4FC16857A@codespeak.net> Author: stephan Date: Mon May 19 17:00:50 2008 New Revision: 54945 Modified: pypy/dist/pypy/translator/goal/targetsimplevideo.py Log: fixed targetsimplevideo.py (cami, stephan) Modified: pypy/dist/pypy/translator/goal/targetsimplevideo.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetsimplevideo.py (original) +++ pypy/dist/pypy/translator/goal/targetsimplevideo.py Mon May 19 17:00:50 2008 @@ -9,6 +9,7 @@ RSDL.Init(RSDL.INIT_VIDEO) >= 0 screen = RSDL.SetVideoMode(WIDTH, HEIGHT, 32, 0) event = lltype.malloc(RSDL.Event, flavor='raw') + paintpattern = 0 try: while True: ok = RSDL.WaitEvent(event) @@ -19,9 +20,12 @@ if rffi.getintfield(p.c_keysym, 'c_sym') == RSDL.K_ESCAPE: print 'Escape key' break - update_screen(screen) + paintpattern += 1 + update_screen(screen, paintpattern) finally: lltype.free(event, flavor='raw') + + return 0 # ----------------------------------------------------------------------------- @@ -67,17 +71,16 @@ # ----------------------------------------------------------------------------- -pattern = (chess, white, black, stripes_v, stripes_m) -current_pattern_id = 0 -def update_screen(screen): - fmt = self.screen.c_format +pattern = [chess, white, black, stripes_v, stripes_m] +pl = len(pattern) +def update_screen(screen, paintpattern): + fmt = screen.c_format white = RSDL.MapRGB(fmt, 255, 255, 255) black = RSDL.MapRGB(fmt, 0, 0, 0) - RSDL.LockSurface(self.screen) - pattern[current_pattern_id % len(pattern)](screen, black, white) - RSDL.UnlockSurface(self.screen) - RSDL.Flip(self.screen) - current_pattern_id += 1 + RSDL.LockSurface(screen) + pattern[paintpattern % pl](screen, black, white) + RSDL.UnlockSurface(screen) + RSDL.Flip(screen) # ----------------------------------------------------------------------------- From afa at codespeak.net Mon May 19 17:03:31 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Mon, 19 May 2008 17:03:31 +0200 (CEST) Subject: [pypy-svn] r54946 - in pypy/branch/win32port/pypy: module/thread rpython/tool translator/c/src Message-ID: <20080519150331.3CF78168534@codespeak.net> Author: afa Date: Mon May 19 17:03:28 2008 New Revision: 54946 Modified: pypy/branch/win32port/pypy/module/thread/ll_thread.py pypy/branch/win32port/pypy/rpython/tool/rffi_platform.py pypy/branch/win32port/pypy/translator/c/src/thread_nt.h Log: Port module/thread to win32. Modified: pypy/branch/win32port/pypy/module/thread/ll_thread.py ============================================================================== --- pypy/branch/win32port/pypy/module/thread/ll_thread.py (original) +++ pypy/branch/win32port/pypy/module/thread/ll_thread.py Mon May 19 17:03:28 2008 @@ -6,7 +6,7 @@ from pypy.rpython.annlowlevel import cast_instance_to_base_ptr from pypy.translator.tool.cbuild import ExternalCompilationInfo from pypy.rpython.lltypesystem import llmemory -import thread, py +import thread, py, os from pypy.rpython.extregistry import ExtRegistryEntry from pypy.annotation import model as annmodel from pypy.rpython.lltypesystem.lltype import typeOf @@ -17,15 +17,26 @@ error = thread.error +_MS_WINDOWS = os.name == "nt" + +if not _MS_WINDOWS: + includes = ['unistd.h'] +else: + includes = [] + eci = ExternalCompilationInfo( - includes = ['unistd.h', 'src/thread.h'], - separate_module_sources=[''' + includes = includes + ['src/thread.h'], + separate_module_sources=[ + ''' #include #include #include '''], include_dirs = [str(py.path.local(autopath.pypydir).join('translator', 'c')), - python_inc] + python_inc], + export_symbols = ['RPyThreadGetIdent', 'RPyThreadLockInit', + 'RPyThreadAcquireLock', 'RPyThreadReleaseLock', + 'RPyThreadFusedReleaseAcquireLock',] ) def llexternal(name, args, result, **kwds): Modified: pypy/branch/win32port/pypy/rpython/tool/rffi_platform.py ============================================================================== --- pypy/branch/win32port/pypy/rpython/tool/rffi_platform.py (original) +++ pypy/branch/win32port/pypy/rpython/tool/rffi_platform.py Mon May 19 17:03:28 2008 @@ -530,8 +530,8 @@ """ def run_example_code(filepath, eci): - eci = eci.convert_sources_to_files() - files = [filepath] + list(eci.separate_module_files) + eci = eci.convert_sources_to_files(being_main=True) + files = [filepath] + [py.path.local(f) for f in eci.separate_module_files] output = build_executable_cache(files, eci) section = None for line in output.splitlines(): Modified: pypy/branch/win32port/pypy/translator/c/src/thread_nt.h ============================================================================== --- pypy/branch/win32port/pypy/translator/c/src/thread_nt.h (original) +++ pypy/branch/win32port/pypy/translator/c/src/thread_nt.h Mon May 19 17:03:28 2008 @@ -19,11 +19,6 @@ * Thread support. */ -/* - * Return the thread Id instead of an handle. The Id is said to uniquely - identify the thread in the system - */ -#define RPyThreadGetIdent GetCurrentThreadId #define RPyOpaque_INITEXPR_ThreadLock { 0, 0, NULL } typedef struct { @@ -54,6 +49,15 @@ #ifndef PYPY_NOT_MAIN_FILE +/* + * Return the thread Id instead of an handle. The Id is said to uniquely + identify the thread in the system + */ +int RPyThreadGetIdent() +{ + return GetCurrentThreadId(); +} + static int bootstrap(void *call) { @@ -201,7 +205,10 @@ /************************************************************/ -#define RPyThreadLockInit(lock) InitializeNonRecursiveMutex(lock) +int RPyThreadLockInit(struct RPyOpaque_ThreadLock * lock) +{ + return InitializeNonRecursiveMutex(lock); +} void RPyOpaqueDealloc_ThreadLock(struct RPyOpaque_ThreadLock *lock) { From afa at codespeak.net Mon May 19 17:22:09 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Mon, 19 May 2008 17:22:09 +0200 (CEST) Subject: [pypy-svn] r54947 - in pypy/branch/win32port/pypy: module/thread translator/c/src Message-ID: <20080519152209.A8E2816841D@codespeak.net> Author: afa Date: Mon May 19 17:22:07 2008 New Revision: 54947 Modified: pypy/branch/win32port/pypy/module/thread/ll_thread.py pypy/branch/win32port/pypy/translator/c/src/thread.h Log: Attempt to remove Python.h from pypy's thread.h. Code seems simpler, but it needs some tests on Unix. Modified: pypy/branch/win32port/pypy/module/thread/ll_thread.py ============================================================================== --- pypy/branch/win32port/pypy/module/thread/ll_thread.py (original) +++ pypy/branch/win32port/pypy/module/thread/ll_thread.py Mon May 19 17:22:07 2008 @@ -17,21 +17,9 @@ error = thread.error -_MS_WINDOWS = os.name == "nt" - -if not _MS_WINDOWS: - includes = ['unistd.h'] -else: - includes = [] - eci = ExternalCompilationInfo( - includes = includes + ['src/thread.h'], - separate_module_sources=[ - ''' - #include - #include - #include - '''], + includes = ['src/thread.h'], + separate_module_sources = [''], include_dirs = [str(py.path.local(autopath.pypydir).join('translator', 'c')), python_inc], export_symbols = ['RPyThreadGetIdent', 'RPyThreadLockInit', Modified: pypy/branch/win32port/pypy/translator/c/src/thread.h ============================================================================== --- pypy/branch/win32port/pypy/translator/c/src/thread.h (original) +++ pypy/branch/win32port/pypy/translator/c/src/thread.h Mon May 19 17:22:07 2008 @@ -3,7 +3,13 @@ #ifndef __PYPY_THREAD_H #define __PYPY_THREAD_H -#include "Python.h" +#include + +#ifdef _WIN32 +#include "thread_nt.h" +#else + +#include #ifndef _POSIX_THREADS /* This means pthreads are not implemented in libc headers, hence the macro @@ -18,9 +24,7 @@ #include "thread_pthread.h" #endif -#ifdef NT_THREADS -#include "thread_nt.h" -#endif +#endif /* !_WIN32 */ #ifdef USE___THREAD From cami at codespeak.net Mon May 19 17:40:02 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Mon, 19 May 2008 17:40:02 +0200 (CEST) Subject: [pypy-svn] r54949 - pypy/dist/pypy/rlib/rsdl Message-ID: <20080519154002.8B34D1684CE@codespeak.net> Author: cami Date: Mon May 19 17:39:57 2008 New Revision: 54949 Removed: pypy/dist/pypy/rlib/rsdl/ Log: remvode beginners rsdl From antocuni at codespeak.net Mon May 19 17:55:27 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 19 May 2008 17:55:27 +0200 (CEST) Subject: [pypy-svn] r54950 - pypy/django/tests Message-ID: <20080519155527.2E9C3168543@codespeak.net> Author: antocuni Date: Mon May 19 17:55:25 2008 New Revision: 54950 Modified: pypy/django/tests/conftest.py Log: (antocuni, fijal) (IN-PROGRESS) more conftest Modified: pypy/django/tests/conftest.py ============================================================================== --- pypy/django/tests/conftest.py (original) +++ pypy/django/tests/conftest.py Mon May 19 17:55:25 2008 @@ -47,25 +47,42 @@ loaded_apps = {} -class Directory(py.test.collect.Directory): - +class Module(py.test.collect.Module): def run(self): - rel = self.fspath.relto(rootdir) - if not rel: - self.level = 0 - return self.run0() - lgt = rel.count(os.path.sep) - if lgt == 0: - self.level = 1 - return self.run1() + from django.conf import settings + mod = self._get_mod() + result = self._tests_from_mod(mod) + modpath = py.path.local(mod.__file__) + for name in ['tests', 'tests.py']: + path = modpath.join('..', name) + if path.check(): + testmod = path.pyimport() + mod.tests = testmod + result += ['tests.' + i for i in self._tests_from_mod(testmod)] + return result + + def _tests_from_mod(self, mod): + result = [] + if hasattr(mod, 'suite'): + import pdb + pdb.set_trace() else: - self.level = 2 - return self.run2() + items = [k for k, v in + mod.__dict__.iteritems() + if isinstance(v, type) and + issubclass(v, unittest.TestCase)] + result += items + result += self._find_doctests(mod) + return result - def run2(self): - from django.conf import settings + def _find_doctests(self, mod): + if hasattr(mod, '__test__') and mod.__test__.get('API_TESTS'): + return ['%docstring%'] + #return [)] + return [] + + def _get_mod(self): from django.db.models.loading import load_app - from django.test.simple import build_suite rel = self.fspath.relto(rootdir) app_name = rel.replace(os.path.sep, '.') if app_name in loaded_apps: @@ -76,16 +93,36 @@ if mod: if app_name not in settings.INSTALLED_APPS: settings.INSTALLED_APPS.append(app_name) + return mod - if hasattr(mod, '__test__') and mod.__test__.get('API_TESTS'): - return [DocTestItem(self.fspath.basename + '.docstring', mod, mod.__test__['API_TESTS'])] - return [] - #suite = build_suite(mod) - #x = suite._tests[1]._tests[0] - #return [x] - #return suite._tests - # modify the global settings + def join(self, name): + mod = self._get_mod() + if name == '%docstring%': + return DocTestItem(self.fspath.basename + '.%docstring%', mod, mod.__test__['API_TESTS']) + elif name == 'tests.%docstring%': + mod = mod.tests + return DocTestItem(self.fspath.basename + '.%docstring%', mod, mod.__test__['API_TESTS']) + elif name.startswith('tests'): + return getattr(mod.tests, name[len('tests.'):]) + else: + return getattr(mod, name) +class Directory(py.test.collect.Directory): + def _level(self): + rel = self.fspath.relto(rootdir) + if not rel: + return 0 + lgt = rel.count(os.path.sep) + if lgt == 0: + return 1 + else: + assert 0 + + def run(self): + level = self._level() + meth = getattr(self, 'run%d' % level) + return meth() + def run1(self): models = [] for model in self.fspath.listdir(): @@ -100,12 +137,11 @@ def run0(self): return DIRNAMES - def join(self, name_or_item): - if isinstance(name_or_item, py.test.collect.Item): - return name_or_item - name = name_or_item + def join(self, name): path = self.fspath.join(name) if path.check(dir=1): + if self._level() == 1: + return Module(self.fspath.join(name)) return Directory(self.fspath.join(name)) else: raise NotImplementedError From cfbolz at codespeak.net Mon May 19 17:58:10 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Mon, 19 May 2008 17:58:10 +0200 (CEST) Subject: [pypy-svn] r54951 - pypy/dist/pypy/rlib/rsdl Message-ID: <20080519155810.9E520168543@codespeak.net> Author: cfbolz Date: Mon May 19 17:58:05 2008 New Revision: 54951 Added: pypy/dist/pypy/rlib/rsdl/ - copied from r54948, pypy/dist/pypy/rlib/rsdl/ Log: (cami, cfbolz): revert commit that accidentially deleted rsdl From cami at codespeak.net Mon May 19 18:30:17 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Mon, 19 May 2008 18:30:17 +0200 (CEST) Subject: [pypy-svn] r54952 - pypy/branch/gameboy-emulator/pypy/lang/gameboy Message-ID: <20080519163017.364841684FB@codespeak.net> Author: cami Date: Mon May 19 18:30:15 2008 New Revision: 54952 Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboyImplementation.py Log: added hackishly thingy for graphicsdriver Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py Mon May 19 18:30:15 2008 @@ -7,7 +7,7 @@ from pypy.lang.gameboy.ram import iMemory -from pypy.rlib.rstr import str_replace +#from pypy.rlib.rstr import str_replace import os Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboyImplementation.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboyImplementation.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/gameboyImplementation.py Mon May 19 18:30:15 2008 @@ -1,10 +1,11 @@ #!/usr/bin/env python import time -from pypy.lang.gameboy.gameboy import * +from pypy.lang.gameboy.gameboy import GameBoy from pypy.lang.gameboy.joypad import JoypadDriver from pypy.lang.gameboy.video import VideoDriver from pypy.lang.gameboy.sound import SoundDriver +from pypy.rlib.rsdl import RSDL, RSDL_helper # GAMEBOY ---------------------------------------------------------------------- @@ -12,10 +13,14 @@ class GameBoyImplementation(GameBoy): def __init__(self): - self.create_window() GameBoy.__init__(self) + self.init_sdl() #self.mainLoop() + def init_sdl(self): + assert RSDL.Init(RSDL.INIT_VIDEO) >= 0 + self.event = lltype.malloc(RSDL.Event, flavor='raw') + def create_window(self): self.win = None #self.win = window.Window() @@ -24,49 +29,46 @@ def create_drivers(self): self.clock = Clock() - self.joypad_driver = JoypadDriverImplementation(self.win) - self.video_driver = VideoDriverImplementation(self.win) + self.joypad_driver = JoypadDriverImplementation() + self.video_driver = VideoDriverImplementation() self.sound_driver = SoundDriverImplementation() def mainLoop(self): - while not self.win.has_exit: - print "i" - self.emulate(5) - time.sleep(0.01) + try: + while not self.win.has_exit: + self.joypad_driver.update( self.event) + self.emulate(5) + time.sleep(0.01) + finally: + lltype.free(event, flavor='raw') return 0 # VIDEO DRIVER ----------------------------------------------------------------- class VideoDriverImplementation(VideoDriver): - def __init__(self, win): + def __init__(self): VideoDriver.__init__(self) - #self.win = win - #self.win.on_resize = self.on_resize - #self.set_window_size() - #self.create_image_buffer() - - def create_image_buffer(self): - #self.buffers = image.get_buffer_manager() - #self.image_buffer = self.buffers.get_color_buffer() - #self.buffer_image_data = self.image_buffer.image_data - #self.buffer_image_data.format = "RGB" - #self.pixel_buffer = self.buffer_image_data.data - pass - - def on_resize(self, width, height): - pass + self.map = [] def set_window_size(self): - #self.win.set_size(self.width, self.height) - pass + self.screen = RSDL.SetVideoMode(self.width, self.height, 32, 0) def update_display(self): - #self.buffer_image_data.data = map(self.pixel_to_byte, self.pixel_buffer) - #self.image_buffer.blit(0, 0) - #self.win.flip() - pass - + RSDL.LockSurface(screen) + self.draw_pixels() + RSDL.UnlockSurface(screen) + RSDL.Flip(screen) + + def draw_pixels(self): + for x in range(self.width): + for y in range(self.height): + RSDL_helper.set_pixel(screen, x, y, self.get_pixel_color(x, y)) + + def get_pixel_color(self, x, y): + return self.pixels[x+self.width*y] + #return self.map[self.pixels[x+self.width*y]] + def pixel_to_byte(self, int_number): return struct.pack("B", (int_number) & 0xFF, (int_number >> 8) & 0xFF, @@ -77,11 +79,28 @@ class JoypadDriverImplementation(JoypadDriver): - def __init__(self, win): + def __init__(self): JoypadDriver.__init__(self) - #self.create_button_key_codes() - self.win = win - #self.create_listeners() + self.last_char = "" + + def update(self, event): + # fetch the event from sdl + ok = RSDL.WaitEvent(event) + assert rffi.cast(lltype.Signed, ok) == 1 + type = rffi.getintfield(event, 'c_type') + if type == RSDL.KEYDOWN: + self.create_called_key() + self.on_key_down() + elif type == RSDL.KEYUP: + self.create_called_key() + self.on_key_up() + + def create_called_key(self, event): + p = rffi.cast(RSDL.KeyboardEventPtr, event) + char = rffi.getintfield(p.c_keysym, 'c_unicode') + self.last_char = unichr(char).encode('utf-8') + + def create_button_key_codes(self): self.button_key_codes = {key.UP : (self.button_up), From cami at codespeak.net Mon May 19 18:37:32 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Mon, 19 May 2008 18:37:32 +0200 (CEST) Subject: [pypy-svn] r54953 - pypy/branch/gameboy-emulator/pypy/lang/gameboy Message-ID: <20080519163732.8379A168542@codespeak.net> Author: cami Date: Mon May 19 18:37:32 2008 New Revision: 54953 Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py Log: reverted changes for str_replace Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py Mon May 19 18:37:32 2008 @@ -194,12 +194,12 @@ def create_battery_file_path(self, cartridge_file_path): if cartridge_file_path.endswith(constants.CARTRIDGE_FILE_EXTENSION): - return str_replace(cartridge_file_path, + return cartridge_file_path.replace( constants.CARTRIDGE_FILE_EXTENSION, constants.BATTERY_FILE_EXTENSION) elif cartridge_file_path.endswith( constants.CARTRIDGE_COLOR_FILE_EXTENSION): - return str_replace(cartridge_file_path, + return cartridge_file_pat.replace( constants.CARTRIDGE_COLOR_FILE_EXTENSION, constants.BATTERY_FILE_EXTENSION) else: From tverwaes at codespeak.net Mon May 19 18:44:10 2008 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Mon, 19 May 2008 18:44:10 +0200 (CEST) Subject: [pypy-svn] r54954 - pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk Message-ID: <20080519164410.BB00A16841A@codespeak.net> Author: tverwaes Date: Mon May 19 18:44:10 2008 New Revision: 54954 Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/interpreter.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py Log: (cfbolz, tverwaes) broken import, in progress (fixing shadows to work redirecting) Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/interpreter.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/interpreter.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/interpreter.py Mon May 19 18:44:10 2008 @@ -1,5 +1,4 @@ import py -from pypy.lang.smalltalk.shadow import Invalidateable from pypy.lang.smalltalk.shadow import ContextPartShadow, MethodContextShadow, BlockContextShadow from pypy.lang.smalltalk import model, constants, primitives from pypy.lang.smalltalk import objtable @@ -18,7 +17,7 @@ class IllegalStoreError(Exception): """Illegal Store.""" -class Interpreter(Invalidateable): +class Interpreter(object): TRUE = objtable.w_true FALSE = objtable.w_false @@ -32,31 +31,17 @@ def __init__(self): self._w_active_context = None - self._s_active_context = None self.cnt = 0 def w_active_context(self): return self._w_active_context def store_w_active_context(self, w_context): - # We can only interpret contexts of which we know the type already - #s_ctx = w_context.as_context_get_shadow() - #assert (isinstance(s_ctx, MethodContextShadow) or - # isinstance(s_ctx, BlockContextShadow)) - if self._s_active_context is not None: - self._s_active_context.unnotify(self) - self._s_active_context = None assert isinstance(w_context, model.W_PointersObject) self._w_active_context = w_context - def invalidate(self): - self._s_active_context = None - def s_active_context(self): - if self._s_active_context is None: - self._s_active_context = self.w_active_context().as_context_get_shadow() - self._s_active_context.notifyinvalid(self) - return self._s_active_context + return self.w_active_context().as_context_get_shadow() def interpret(self): try: Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py Mon May 19 18:44:10 2008 @@ -224,13 +224,18 @@ def fetch(self, n0): if self._shadow is not None: - self._shadow.sync_w_self() + return self._shadow.fetch(n0) + return self._fetch(n0) + + def _fetch(self, n0): return self._vars[n0] def store(self, n0, w_value): if self._shadow is not None: - self._shadow.sync_w_self() - self._shadow.invalidate_shadow() + return self._shadow.store(n0, w_value) + return self._store(n0, w_value) + + def _store(self, n0, w_value): self._vars[n0] = w_value # def fetchvarpointer(self, idx): @@ -557,7 +562,6 @@ s_result.store_w_home(w_home) s_result._stack = [] s_result._pc = initialip - s_result.invalidate_w_self() return w_result def W_MethodContext(w_method, w_receiver, @@ -578,7 +582,6 @@ for i in range(len(arguments)): s_result.settemp(i, arguments[i]) s_result._stack = [] - s_result.invalidate_w_self() return w_result # Use black magic to create w_nil without running the constructor, Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py Mon May 19 18:44:10 2008 @@ -2,54 +2,33 @@ from pypy.lang.smalltalk import model, constants, utility, error from pypy.tool.pairtype import extendabletype -class Invalidateable(object): - def invalidate_shadow(self): - pass - -class AbstractShadow(Invalidateable): +class AbstractShadow(object): """A shadow is an optional extra bit of information that can be attached at run-time to any Smalltalk object. """ - - def __init__(self, w_self, invalid): + def __init__(self, w_self): self._w_self = w_self - self._notifyinvalid = [] - self.invalid = invalid - self.w_invalid = False - if invalid: - self.invalidate_shadow() - - def notifyinvalid(self, other): - self._notifyinvalid += [other] - - def unnotify(self, other): - if other in self._notifyinvalid: - self._notifyinvalid.remove(other) - + def fetch(self, n0): + return self.w_self()._fetch(n0) + def store(self, n0, w_value): + return self.w_self()._store(n0, w_value) + def w_self(self): + return self._w_self def getname(self): return repr(self) + def detach_shadow(self): + pass + +class AbstractCachingShadow(AbstractShadow): + def __init__(self, w_self): + AbstractShadow.__init__(self, w_self) + self.update_shadow() def invalidate_shadow(self): - """XXX This should get called whenever the base Smalltalk + """This should get called whenever the base Smalltalk object changes.""" if not self.invalid: self.invalid = True - for listener in self._notifyinvalid: - listener.invalidate_shadow() - self._notifyinvalid = [] - - def invalidate_w_self(self): - """XXX This should get called whenever the shadow - object changes. - (current shortcut, whenever the shadow is used)""" - self.w_invalid = True - - def w_self(self): - return self._w_self - - def sync_w_self(self): - if self.w_invalid: - self.update_w_self() def sync_shadow(self): if self.invalid: @@ -58,9 +37,14 @@ def update_shadow(self): self.w_self().setshadow(self) self.invalid = False + self.sync_cache() - def update_w_self(self): - self.w_invalid = False + def sync_cache(self): + raise NotImplementedError() + + def store(self, n0, w_value): + self.invalidate_shadow() + AbstractShadow.store(self, n0, w_value) # ____________________________________________________________ @@ -77,13 +61,10 @@ class ClassShadowError(error.SmalltalkException): pass -class ClassShadow(AbstractShadow): +class ClassShadow(AbstractCachingShadow): """A shadow for Smalltalk objects that are classes (i.e. used as the class of another Smalltalk object). """ - def __init__(self, w_self, invalid): - AbstractShadow.__init__(self, w_self, invalid) - def invalidate_shadow(self): AbstractShadow.invalidate_shadow(self) self.w_methoddict = None @@ -93,7 +74,7 @@ def getname(self): return "%s class" % (self.name or '?',) - def update_shadow(self): + def sync_cache(self): from pypy.lang.smalltalk import objtable "Update the ClassShadow with data from the w_self class." @@ -263,14 +244,13 @@ if isinstance(method, model.W_CompiledMethod): method.w_compiledin = self.w_self() -class MethodDictionaryShadow(AbstractShadow): - def __init__(self, w_self, invalid): - AbstractShadow.__init__(self, w_self, invalid) +class MethodDictionaryShadow(AbstractCachingShadow): def invalidate_shadow(self): + AbstractCachingShadow.invalidate_shadow(self) self.methoddict = None - def update_shadow(self): + def sync_cache(self): from pypy.lang.smalltalk import objtable w_values = self.w_self()._vars[constants.METHODDICT_VALUES_INDEX] assert isinstance(w_values, model.W_PointersObject) @@ -290,39 +270,68 @@ "CompiledMethods only for now") self.methoddict[selector] = w_compiledmethod -class ContextPartShadow(AbstractShadow): + +class AbstractRedirectingShadow(AbstractShadow): + def __init__(self, w_self): + AbstractShadow.__init__(self, w_self) + self._w_self_size = len(self.w_self()._vars) + def fetch(self, n0): + raise NotImplementedError() + def store(self, n0, w_value): + raise NotImplementedError() + +class ContextPartShadow(AbstractRedirectingShadow): __metaclass__ = extendabletype + def fetch(self, n0): + if n0 == constants.CTXPART_SENDER_INDEX: + return self.w_sender() + if n0 == constants.CTXPART_PC_INDEX: + return self.wrap_pc() + if n0 == constants.CTXPART_STACKP_INDEX: + return utility.wrap_int(self.stackpointer()) + if self.stackstart() <= n0 < self.stackpointer(): + return self._stack[n0-self.stackstart()] + if self.stackpointer() <= n0 < self.stackend(): + return objtable.w_nil + else: + # XXX later should store tail out of known context part as well + raise error.WrapperException("Index in context out of bounds") + + def store(self, n0, w_value): + if n0 == constants.CTXPART_SENDER_INDEX: + return self.store_w_sender(w_value) + if n0 == constants.CTXPART_PC_INDEX: + return self.store_unwrap_pc(w_value) + if n0 == constants.CTXPART_STACKP_INDEX: + return self.store_stackpointer(utility.unwrap_int(w_value)) + if self.stackstart() <= n0 < self.stackpointer(): + return self._stack[n0-self.stackstart()] = w_value + if self.stackpointer() <= n0 < self.stackend(): + raise error.WrapperException( + "Trying to store within stack range, after actual stack") + else: + # XXX later should store tail out of known context part as well + raise error.WrapperException("Index in context out of bounds") + def update_shadow(self): + # XXX We need the method before reading pc + # and stack (islarge -> stack + args + locals size) AbstractShadow.update_shadow(self) - self._stack = [self.w_self()._vars[i] - for i in range(self.stackstart(), - self.stackpointer())] - self.init_pc() - # Using a shadow most likely results in an invalid state for w_self - self.invalidate_w_self() + for i in range(self._w_self_size): + self.store(i, self.w_self()._fetch(i)) - def init_pc(self): - self._pc = utility.unwrap_int(self.w_self()._vars[constants.CTXPART_PC_INDEX]) + def store_unwrap_pc(self, w_pc): + self._pc = utility.unwrap_int(w_pc) self._pc -= self.w_method().bytecodeoffset() self._pc -= 1 - def save_back_pc(self): + def wrap_pc(self): pc = self._pc pc += 1 pc += self.w_method().bytecodeoffset() - self.w_self()._vars[constants.CTXPART_PC_INDEX] = utility.wrap_int(pc) - - def update_w_self(self): - AbstractShadow.update_w_self(self) - for i in range(len(self._stack)): - self.w_self()._vars[self.stackstart() + i] = self._stack[i] - self.store_stackpointer(len(self._stack)) - self.save_back_pc() - - def __init__(self, w_self, invalid): - AbstractShadow.__init__(self, w_self, invalid) + return utility.wrap_int(pc) def w_home(self): raise NotImplementedError() @@ -440,9 +449,9 @@ class BlockContextShadow(ContextPartShadow): - def __init__(self, w_self, invalid): + def __init__(self, w_self): self._s_home = None - ContextPartShadow.__init__(self, w_self, invalid) + ContextPartShadow.__init__(self, w_self) def invalidate_shadow(self): if self._s_home is not None: From afa at codespeak.net Mon May 19 18:48:51 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Mon, 19 May 2008 18:48:51 +0200 (CEST) Subject: [pypy-svn] r54955 - pypy/branch/win32port/pypy/rlib Message-ID: <20080519164851.975AA1684FA@codespeak.net> Author: afa Date: Mon May 19 18:48:50 2008 New Revision: 54955 Modified: pypy/branch/win32port/pypy/rlib/rmmap.py pypy/branch/win32port/pypy/rlib/rsocket.py pypy/branch/win32port/pypy/rlib/rwin32.py Log: Move some definitions from rmmap to rwin32 Modified: pypy/branch/win32port/pypy/rlib/rmmap.py ============================================================================== --- pypy/branch/win32port/pypy/rlib/rmmap.py (original) +++ pypy/branch/win32port/pypy/rlib/rmmap.py Mon May 19 18:48:50 2008 @@ -38,19 +38,7 @@ size_t = rffi_platform.SimpleType("size_t", rffi.LONG) off_t = rffi_platform.SimpleType("off_t", rffi.LONG) if _MS_WINDOWS: - DWORD_PTR = rffi_platform.SimpleType("DWORD_PTR", rffi.LONG) - WORD = rffi_platform.SimpleType("WORD", rffi.UINT) - DWORD = rffi_platform.SimpleType("DWORD", rffi.ULONG) - BOOL = rffi_platform.SimpleType("BOOL", rffi.LONG) - INT = rffi_platform.SimpleType("INT", rffi.INT) - LONG = rffi_platform.SimpleType("LONG", rffi.LONG) - PLONG = rffi_platform.SimpleType("PLONG", rffi.LONGP) - LPVOID = rffi_platform.SimpleType("LPVOID", rffi.INTP) - LPCVOID = rffi_platform.SimpleType("LPCVOID", rffi.VOIDP) - LPCTSTR = rffi_platform.SimpleType("LPCTSTR", rffi.CCHARP) - LPDWORD = rffi_platform.SimpleType("LPDWORD", rffi.INTP) LPSECURITY_ATTRIBUTES = rffi_platform.SimpleType("LPSECURITY_ATTRIBUTES", rffi.CCHARP) - SIZE_T = rffi_platform.SimpleType("SIZE_T", rffi.SIZE_T) constants = {} if _POSIX: @@ -80,8 +68,10 @@ for name in constant_names: setattr(CConfig, name, rffi_platform.ConstantInteger(name)) - HANDLE = rffi.ULONG - LPHANDLE = rffi.CArrayPtr(HANDLE) + from pypy.rlib.rwin32 import HANDLE, LPHANDLE + from pypy.rlib.rwin32 import DWORD, WORD, DWORD_PTR, LPDWORD + from pypy.rlib.rwin32 import BOOL, LPVOID, LPCVOID, LPCTSTR, SIZE_T + from pypy.rlib.rwin32 import INT, LONG, PLONG # export the constants inside and outside. see __init__.py cConfig = rffi_platform.configure(CConfig) Modified: pypy/branch/win32port/pypy/rlib/rsocket.py ============================================================================== --- pypy/branch/win32port/pypy/rlib/rsocket.py (original) +++ pypy/branch/win32port/pypy/rlib/rsocket.py Mon May 19 18:48:50 2008 @@ -153,8 +153,7 @@ flags=AI_PASSIVE, address_to_fill=result) if len(info) > 1: - raise RSocketError("wildcard resolved to " - "multiple addresses") + raise RSocketError("wildcard resolved to multiple addresses") return info[0][4] # IPv4 also supports the special name "". Modified: pypy/branch/win32port/pypy/rlib/rwin32.py ============================================================================== --- pypy/branch/win32port/pypy/rlib/rwin32.py (original) +++ pypy/branch/win32port/pypy/rlib/rwin32.py Mon May 19 18:48:50 2008 @@ -23,11 +23,20 @@ _compilation_info_ = eci if WIN32: + DWORD_PTR = rffi_platform.SimpleType("DWORD_PTR", rffi.LONG) + WORD = rffi_platform.SimpleType("WORD", rffi.UINT) DWORD = rffi_platform.SimpleType("DWORD", rffi.UINT) BOOL = rffi_platform.SimpleType("BOOL", rffi.LONG) - HRESULT = rffi_platform.SimpleType("HRESULT", rffi.LONG) + INT = rffi_platform.SimpleType("INT", rffi.INT) + LONG = rffi_platform.SimpleType("LONG", rffi.LONG) + PLONG = rffi_platform.SimpleType("PLONG", rffi.LONGP) + LPVOID = rffi_platform.SimpleType("LPVOID", rffi.INTP) + LPCVOID = rffi_platform.SimpleType("LPCVOID", rffi.VOIDP) + LPCTSTR = rffi_platform.SimpleType("LPCTSTR", rffi.CCHARP) + LPDWORD = rffi_platform.SimpleType("LPDWORD", rffi.INTP) + SIZE_T = rffi_platform.SimpleType("SIZE_T", rffi.SIZE_T) - HANDLE = rffi_platform.SimpleType("HANDLE", rffi.VOIDP) + HRESULT = rffi_platform.SimpleType("HRESULT", rffi.LONG) HLOCAL = rffi_platform.SimpleType("HLOCAL", rffi.VOIDP) DEFAULT_LANGUAGE = rffi_platform.ConstantInteger( @@ -45,6 +54,9 @@ return rffi.llexternal(name, args, result, compilation_info=eci, calling_conv='win') if WIN32: + HANDLE = rffi.ULONG + LPHANDLE = rffi.CArrayPtr(HANDLE) + GetLastError = winexternal('GetLastError', [], DWORD) LoadLibrary = winexternal('LoadLibraryA', [rffi.CCHARP], rffi.VOIDP) From arigo at codespeak.net Mon May 19 19:01:15 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 19 May 2008 19:01:15 +0200 (CEST) Subject: [pypy-svn] r54956 - in pypy/dist/pypy: interpreter objspace/std Message-ID: <20080519170115.034EA168471@codespeak.net> Author: arigo Date: Mon May 19 19:01:11 2008 New Revision: 54956 Modified: pypy/dist/pypy/interpreter/typedef.py pypy/dist/pypy/objspace/std/nonetype.py Log: (pedronis, arigo) Make a few types unsubclassable. Modified: pypy/dist/pypy/interpreter/typedef.py ============================================================================== --- pypy/dist/pypy/interpreter/typedef.py (original) +++ pypy/dist/pypy/interpreter/typedef.py Mon May 19 19:01:11 2008 @@ -865,12 +865,14 @@ Ellipsis.typedef = TypeDef("Ellipsis", __repr__ = interp2app(Ellipsis.descr__repr__), ) +Ellipsis.acceptable_as_base_class = False NotImplemented.typedef = TypeDef("NotImplemented", __repr__ = interp2app(NotImplemented.descr__repr__), ) SuspendedUnroller.typedef = TypeDef("SuspendedUnroller") +SuspendedUnroller.acceptable_as_base_class = False interptypes = [ val.typedef for name,val in globals().items() if hasattr(val,'__bases__') and hasattr(val,'typedef') ] Modified: pypy/dist/pypy/objspace/std/nonetype.py ============================================================================== --- pypy/dist/pypy/objspace/std/nonetype.py (original) +++ pypy/dist/pypy/objspace/std/nonetype.py Mon May 19 19:01:11 2008 @@ -5,3 +5,4 @@ none_typedef = StdTypeDef("NoneType", ) +none_typedef.acceptable_as_base_class = False From antocuni at codespeak.net Mon May 19 19:47:33 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 19 May 2008 19:47:33 +0200 (CEST) Subject: [pypy-svn] r54957 - pypy/django/tests Message-ID: <20080519174733.A3E48168534@codespeak.net> Author: antocuni Date: Mon May 19 19:47:31 2008 New Revision: 54957 Modified: pypy/django/tests/conftest.py Log: fix import Modified: pypy/django/tests/conftest.py ============================================================================== --- pypy/django/tests/conftest.py (original) +++ pypy/django/tests/conftest.py Mon May 19 19:47:31 2008 @@ -49,7 +49,6 @@ class Module(py.test.collect.Module): def run(self): - from django.conf import settings mod = self._get_mod() result = self._tests_from_mod(mod) modpath = py.path.local(mod.__file__) @@ -83,6 +82,7 @@ def _get_mod(self): from django.db.models.loading import load_app + from django.conf import settings rel = self.fspath.relto(rootdir) app_name = rel.replace(os.path.sep, '.') if app_name in loaded_apps: From afa at codespeak.net Mon May 19 20:42:21 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Mon, 19 May 2008 20:42:21 +0200 (CEST) Subject: [pypy-svn] r54958 - pypy/branch/win32port/pypy/lib Message-ID: <20080519184221.65C8216853A@codespeak.net> Author: afa Date: Mon May 19 20:42:18 2008 New Revision: 54958 Added: pypy/branch/win32port/pypy/lib/_subprocess.py pypy/branch/win32port/pypy/lib/msvcrt.py Log: Quick and dirty _subprocess & msvcrt modules for win32. Most of test_subprocess.py passes! Seems to have problem with threading. Added: pypy/branch/win32port/pypy/lib/_subprocess.py ============================================================================== --- (empty file) +++ pypy/branch/win32port/pypy/lib/_subprocess.py Mon May 19 20:42:18 2008 @@ -0,0 +1,177 @@ +import ctypes as _ctypes + +class _handle: + def __init__(self, handle): + self.handle = handle + + def __int__(self): + return self.handle + + def Detach(self): + handle, self.handle = self.handle, None + return handle + + def Close(self): + _CloseHandle = _ctypes.WinDLL('kernel32').CloseHandle + _CloseHandle.argtypes = [_ctypes.c_int] + _CloseHandle.restype = _ctypes.c_int + + if self.handle not in (-1, None): + _CloseHandle(self.handle) + self.handle = None + +def CreatePipe(attributes, size): + _CreatePipe = _ctypes.WinDLL('kernel32').CreatePipe + _CreatePipe.argtypes = [_ctypes.POINTER(_ctypes.c_int), _ctypes.POINTER(_ctypes.c_int), + _ctypes.c_void_p, _ctypes.c_int] + _CreatePipe.restype = _ctypes.c_int + + read = _ctypes.c_int() + write = _ctypes.c_int() + + res = _CreatePipe(_ctypes.byref(read), _ctypes.byref(write), None, size) + + if not res: + raise WindowsError("Error") + + return _handle(read.value), _handle(write.value) + +def GetCurrentProcess(): + _GetCurrentProcess = _ctypes.WinDLL('kernel32').GetCurrentProcess + _GetCurrentProcess.argtypes = [] + _GetCurrentProcess.restype = _ctypes.c_int + + return _handle(_GetCurrentProcess()) + + +def DuplicateHandle(source_process, source, target_process, access, inherit, options=0): + _DuplicateHandle = _ctypes.WinDLL('kernel32').DuplicateHandle + _DuplicateHandle.argtypes = [_ctypes.c_int, _ctypes.c_int, _ctypes.c_int, + _ctypes.POINTER(_ctypes.c_int), + _ctypes.c_int, _ctypes.c_int, _ctypes.c_int] + _DuplicateHandle.restype = _ctypes.c_int + + target = _ctypes.c_int() + + res = _DuplicateHandle(int(source_process), int(source), int(target_process), + _ctypes.byref(target), + access, inherit, options) + + if not res: + raise WindowsError("Error") + + return _handle(target.value) +DUPLICATE_SAME_ACCESS = 2 + + +def CreateProcess(name, command_line, process_attr, thread_attr, + inherit, flags, env, start_dir, startup_info): + _CreateProcess = _ctypes.WinDLL('kernel32').CreateProcessA + _CreateProcess.argtypes = [_ctypes.c_char_p, _ctypes.c_char_p, _ctypes.c_void_p, _ctypes.c_void_p, + _ctypes.c_int, _ctypes.c_int, _ctypes.c_char_p, _ctypes.c_char_p, + _ctypes.c_void_p, _ctypes.c_void_p] + _CreateProcess.restype = _ctypes.c_int + + class STARTUPINFO(_ctypes.Structure): + _fields_ = [('cb', _ctypes.c_int), + ('lpReserved', _ctypes.c_void_p), + ('lpDesktop', _ctypes.c_char_p), + ('lpTitle', _ctypes.c_char_p), + ('dwX', _ctypes.c_int), + ('dwY', _ctypes.c_int), + ('dwXSize', _ctypes.c_int), + ('dwYSize', _ctypes.c_int), + ('dwXCountChars', _ctypes.c_int), + ('dwYCountChars', _ctypes.c_int), + ("dwFillAttribute", _ctypes.c_int), + ("dwFlags", _ctypes.c_int), + ("wShowWindow", _ctypes.c_int), + ("cbReserved2", _ctypes.c_int), + ("lpReserved2", _ctypes.c_void_p), + ("hStdInput", _ctypes.c_int), + ("hStdOutput", _ctypes.c_int), + ("hStdError", _ctypes.c_int) + ] + + class PROCESS_INFORMATION(_ctypes.Structure): + _fields_ = [("hProcess", _ctypes.c_int), + ("hThread", _ctypes.c_int), + ("dwProcessID", _ctypes.c_int), + ("dwThreadID", _ctypes.c_int)] + + def __init__(self): + Structure.__init__(self) + + self.cb = sizeof(self) + + si = STARTUPINFO() + si.dwFlags = startup_info.dwFlags + si.wShowWindow = getattr(startup_info, 'wShowWindow', 0) + if startup_info.hStdInput: + si.hStdInput = startup_info.hStdInput.handle + if startup_info.hStdInput: + si.hStdOutput = startup_info.hStdOutput.handle + if startup_info.hStdError: + si.hStdError = startup_info.hStdError.handle + + pi = PROCESS_INFORMATION() + + if env is not None: + envbuf = "" + for k, v in env.iteritems(): + envbuf += "%s=%s\0" % (k, v) + envbuf += '\0' + else: + envbuf = None + + res = _CreateProcess(name, command_line, None, None, inherit, flags, envbuf, + start_dir, _ctypes.byref(si), _ctypes.byref(pi)) + + if not res: + raise WindowsError("Error") + + return _handle(pi.hProcess), _handle(pi.hThread), pi.dwProcessID, pi.dwThreadID +STARTF_USESTDHANDLES = 0x100 + +def WaitForSingleObject(handle, milliseconds): + _WaitForSingleObject = _ctypes.WinDLL('kernel32').WaitForSingleObject + _WaitForSingleObject.argtypes = [_ctypes.c_int, _ctypes.c_int] + _WaitForSingleObject.restype = _ctypes.c_int + + res = _WaitForSingleObject(handle.handle, milliseconds) + + if res < 0: + raise WindowsError("Error") + + return res +INFINITE = 0xffffffff +WAIT_OBJECT_0 = 0 + +def GetExitCodeProcess(handle): + _GetExitCodeProcess = _ctypes.WinDLL('kernel32').GetExitCodeProcess + _GetExitCodeProcess.argtypes = [_ctypes.c_int, _ctypes.POINTER(_ctypes.c_int)] + _GetExitCodeProcess.restype = _ctypes.c_int + + code = _ctypes.c_int() + + res = _GetExitCodeProcess(handle.handle, _ctypes.byref(code)) + + if not res: + raise WindowsError("Error") + + return code.value + +def GetStdHandle(stdhandle): + _GetStdHandle = _ctypes.WinDLL('kernel32').GetStdHandle + _GetStdHandle.argtypes = [_ctypes.c_int] + _GetStdHandle.restype = _ctypes.c_int + + res = _GetStdHandle(stdhandle) + + if not res: + return None + else: + return res +STD_INPUT_HANDLE = -10 +STD_OUTPUT_HANDLE = -11 +STD_ERROR_HANDLE = -12 Added: pypy/branch/win32port/pypy/lib/msvcrt.py ============================================================================== --- (empty file) +++ pypy/branch/win32port/pypy/lib/msvcrt.py Mon May 19 20:42:18 2008 @@ -0,0 +1,14 @@ +import _rawffi +import ctypes + +_c = ctypes.CDLL(_rawffi.libc_name) + +open_osfhandle = _c._open_osfhandle +open_osfhandle.argtypes = [ctypes.c_int, ctypes.c_int] +open_osfhandle.restype = ctypes.c_int + +get_osfhandle = _c._get_osfhandle +get_osfhandle.argtypes = [ctypes.c_int] +open_osfhandle.restype = ctypes.c_int + +del ctypes From cami at codespeak.net Tue May 20 11:05:08 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Tue, 20 May 2008 11:05:08 +0200 (CEST) Subject: [pypy-svn] r54984 - pypy/branch/gameboy-emulator/pypy/lang/gameboy Message-ID: <20080520090508.7E593168519@codespeak.net> Author: cami Date: Tue May 20 11:05:05 2008 New Revision: 54984 Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py Log: some dwarfy changes Modified: pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py ============================================================================== --- pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py (original) +++ pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py Tue May 20 11:05:05 2008 @@ -199,7 +199,7 @@ constants.BATTERY_FILE_EXTENSION) elif cartridge_file_path.endswith( constants.CARTRIDGE_COLOR_FILE_EXTENSION): - return cartridge_file_pat.replace( + return cartridge_file_path.replace( constants.CARTRIDGE_COLOR_FILE_EXTENSION, constants.BATTERY_FILE_EXTENSION) else: From cami at codespeak.net Tue May 20 11:09:25 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Tue, 20 May 2008 11:09:25 +0200 (CEST) Subject: [pypy-svn] r54985 - in pypy/dist/pypy: lang/gameboy rlib/rsdl rlib/rsdl/test translator/goal Message-ID: <20080520090925.E29BB168524@codespeak.net> Author: cami Date: Tue May 20 11:09:25 2008 New Revision: 54985 Added: pypy/dist/pypy/lang/gameboy/ - copied from r54952, pypy/branch/gameboy-emulator/pypy/lang/gameboy/ pypy/dist/pypy/lang/gameboy/cartridge.py - copied unchanged from r54984, pypy/branch/gameboy-emulator/pypy/lang/gameboy/cartridge.py pypy/dist/pypy/translator/goal/targetgbrom4.py - copied unchanged from r54952, pypy/branch/gameboy-emulator/pypy/translator/goal/targetgbrom4.py Modified: pypy/dist/pypy/rlib/rsdl/RSDL.py pypy/dist/pypy/rlib/rsdl/test/test_video.py Log: moved gameboy branch Modified: pypy/dist/pypy/rlib/rsdl/RSDL.py ============================================================================== --- pypy/dist/pypy/rlib/rsdl/RSDL.py (original) +++ pypy/dist/pypy/rlib/rsdl/RSDL.py Tue May 20 11:09:25 2008 @@ -122,9 +122,9 @@ # ------------------------------------------------------------------------------ def Init(flags): -# if sys.platform == 'darwin': -# from AppKit import NSApplication -# NSApplication.sharedApplication() + if sys.platform == 'darwin': + from AppKit import NSApplication + NSApplication.sharedApplication() return _Init(flags) # ------------------------------------------------------------------------------ Modified: pypy/dist/pypy/rlib/rsdl/test/test_video.py ============================================================================== --- pypy/dist/pypy/rlib/rsdl/test/test_video.py (original) +++ pypy/dist/pypy/rlib/rsdl/test/test_video.py Tue May 20 11:09:25 2008 @@ -210,7 +210,6 @@ c = white else: c = black - RSDL_helper.set_pixel(self.screen, i, j, c) RSDL.UnlockSurface(self.screen) RSDL.Flip(self.screen) From hpk at codespeak.net Tue May 20 11:40:31 2008 From: hpk at codespeak.net (hpk at codespeak.net) Date: Tue, 20 May 2008 11:40:31 +0200 (CEST) Subject: [pypy-svn] r54986 - in pypy/django: . tests Message-ID: <20080520094031.7BDD716853A@codespeak.net> Author: hpk Date: Tue May 20 11:40:29 2008 New Revision: 54986 Modified: pypy/django/ (props changed) pypy/django/tests/conftest.py Log: (anto, hpk) add pysqlite3 as an external for now automatically add django to python module lookup path rename classes Modified: pypy/django/tests/conftest.py ============================================================================== --- pypy/django/tests/conftest.py (original) +++ pypy/django/tests/conftest.py Tue May 20 11:40:29 2008 @@ -5,6 +5,9 @@ # XXX ignores invalid models path rootdir = py.path.local(__file__).dirpath() +pkgroot = rootdir.dirpath() +if str(pkgroot) not in py.std.sys.path: + py.std.sys.path.append(str(pkgroot)) DIRNAMES = ['modeltests', 'regressiontests']#, 'django/contrib'] @@ -47,7 +50,7 @@ loaded_apps = {} -class Module(py.test.collect.Module): +class DjangoTestModule(py.test.collect.Module): def run(self): mod = self._get_mod() result = self._tests_from_mod(mod) @@ -62,15 +65,15 @@ def _tests_from_mod(self, mod): result = [] - if hasattr(mod, 'suite'): - import pdb - pdb.set_trace() - else: - items = [k for k, v in - mod.__dict__.iteritems() - if isinstance(v, type) and - issubclass(v, unittest.TestCase)] - result += items + #if hasattr(mod, 'suite'): + # import pdb + # pdb.set_trace() + #else: + # items = [k for k, v in + # mod.__dict__.iteritems() + # if isinstance(v, type) and + # issubclass(v, unittest.TestCase)] + # result += items result += self._find_doctests(mod) return result @@ -107,7 +110,7 @@ else: return getattr(mod, name) -class Directory(py.test.collect.Directory): +class DjangoTestDirectory(py.test.collect.Directory): def _level(self): rel = self.fspath.relto(rootdir) if not rel: @@ -141,8 +144,8 @@ path = self.fspath.join(name) if path.check(dir=1): if self._level() == 1: - return Module(self.fspath.join(name)) - return Directory(self.fspath.join(name)) + return DjangoTestModule(self.fspath.join(name)) + return DjangoTestDirectory(self.fspath.join(name)) else: raise NotImplementedError @@ -187,3 +190,7 @@ get_apps() setup() + + +Directory = DjangoTestDirectory +Module = DjangoTestModule From afa at codespeak.net Tue May 20 11:44:14 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 20 May 2008 11:44:14 +0200 (CEST) Subject: [pypy-svn] r54988 - pypy/branch/win32port/pypy/lib Message-ID: <20080520094414.D3C9016853C@codespeak.net> Author: afa Date: Tue May 20 11:44:13 2008 New Revision: 54988 Modified: pypy/branch/win32port/pypy/lib/_subprocess.py Log: Corrections in _subprocess.py for windows. More subprocess tests pass Modified: pypy/branch/win32port/pypy/lib/_subprocess.py ============================================================================== --- pypy/branch/win32port/pypy/lib/_subprocess.py (original) +++ pypy/branch/win32port/pypy/lib/_subprocess.py Tue May 20 11:44:13 2008 @@ -85,31 +85,26 @@ ('dwYCountChars', _ctypes.c_int), ("dwFillAttribute", _ctypes.c_int), ("dwFlags", _ctypes.c_int), - ("wShowWindow", _ctypes.c_int), - ("cbReserved2", _ctypes.c_int), + ("wShowWindow", _ctypes.c_short), + ("cbReserved2", _ctypes.c_short), ("lpReserved2", _ctypes.c_void_p), ("hStdInput", _ctypes.c_int), ("hStdOutput", _ctypes.c_int), ("hStdError", _ctypes.c_int) ] - + class PROCESS_INFORMATION(_ctypes.Structure): _fields_ = [("hProcess", _ctypes.c_int), ("hThread", _ctypes.c_int), ("dwProcessID", _ctypes.c_int), ("dwThreadID", _ctypes.c_int)] - - def __init__(self): - Structure.__init__(self) - - self.cb = sizeof(self) si = STARTUPINFO() si.dwFlags = startup_info.dwFlags si.wShowWindow = getattr(startup_info, 'wShowWindow', 0) if startup_info.hStdInput: si.hStdInput = startup_info.hStdInput.handle - if startup_info.hStdInput: + if startup_info.hStdOutput: si.hStdOutput = startup_info.hStdOutput.handle if startup_info.hStdError: si.hStdError = startup_info.hStdError.handle From arigo at codespeak.net Tue May 20 12:50:56 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 20 May 2008 12:50:56 +0200 (CEST) Subject: [pypy-svn] r54989 - in pypy/dist/pypy: config objspace/std objspace/std/test Message-ID: <20080520105056.9FB9116850D@codespeak.net> Author: arigo Date: Tue May 20 12:50:54 2008 New Revision: 54989 Modified: pypy/dist/pypy/config/pypyoption.py pypy/dist/pypy/objspace/std/multimethod.py pypy/dist/pypy/objspace/std/test/test_multimethod.py Log: (pedronis, arigo) Fix the multimethod installer version 2 to support builtinshortcut. Basic tests on a translated pypy-c seem to work (and give good speed). Modified: pypy/dist/pypy/config/pypyoption.py ============================================================================== --- pypy/dist/pypy/config/pypyoption.py (original) +++ pypy/dist/pypy/config/pypyoption.py Tue May 20 12:50:54 2008 @@ -322,7 +322,7 @@ ("objspace.std.withmethodcache", True), # ("objspace.std.withfastslice", True), ("objspace.std.withprebuiltchar", True), -# ("objspace.std.builtinshortcut", True), + ("objspace.std.builtinshortcut", True), ("objspace.std.optimized_list_getitem", True), ("objspace.std.getattributeshortcut", True), ("translation.list_comprehension_operations",True), Modified: pypy/dist/pypy/objspace/std/multimethod.py ============================================================================== --- pypy/dist/pypy/objspace/std/multimethod.py (original) +++ pypy/dist/pypy/objspace/std/multimethod.py Tue May 20 12:50:54 2008 @@ -524,13 +524,29 @@ for t1, num in self.typenum.items(): setattr(t1, self.attrname, num) self.indexarray = CompressedArray(0) - self.strict_subclasses = {} - for cls1 in list_of_types: - lst = [] - for cls2 in list_of_types: - if cls1 is not cls2 and issubclass(cls2, cls1): - lst.append(cls2) - self.strict_subclasses[cls1] = lst + + def get_typenum(self, cls): + return self.typenum[cls] + + def is_anti_range(self, typenums): + # NB. typenums should be sorted. Returns (a, b) if typenums contains + # at least half of all typenums and its complement is range(a, b). + # Returns (None, None) otherwise. Returns (0, 0) if typenums contains + # everything. + n = len(self.list_of_types) + if len(typenums) <= n // 2: + return (None, None) + typenums = dict.fromkeys(typenums) + complement = [typenum for typenum in range(n) + if typenum not in typenums] + if not complement: + return (0, 0) + a = min(complement) + b = max(complement) + 1 + if complement == range(a, b): + return (a, b) + else: + return (None, None) def normalize_length(self, next_array): # make sure that the indexarray is not smaller than any funcarray @@ -600,7 +616,7 @@ return self._function name = self.get_function_name() self.compress_typechecks(mrdtable) - checklines = self.generate_typechecks(fnargs[nbargs_before:]) + checklines = self.generate_typechecks(mrdtable, fnargs[nbargs_before:]) if not checklines: body = self.body else: @@ -649,61 +665,116 @@ fulls += 1 if fulls == types_total: return 1 - - # a word about subclasses: we are using isinstance() to do - # the checks in generate_typechecks(), which is a - # compromize. In theory we should check the type ids - # instead. But using isinstance() is better because the - # annotator can deduce information from that. It is still - # correct to use isinstance() instead of type ids in - # "reasonable" cases, though -- where "reasonable" means - # that classes always have a delegate to their superclasses, - # e.g. W_IntObject delegates to W_Root. If this is true - # then both kind of checks are good enough to spot - # mismatches caused by the compression table. - - # Based on this reasoning, we can compress the typechecks a - # bit more - if we accept W_Root, for example, then we - # don't have to specifically accept W_IntObject too. - for cls, subnode in node.items(): - for cls2 in mrdtable.strict_subclasses[cls]: - if cls2 in node and node[cls2] == subnode: - del node[cls2] - return 0 types_total = len(mrdtable.list_of_types) if full(self.typetree): self.typetree = True - def generate_typechecks(self, args): + def generate_typechecks(self, mrdtable, args): + attrname = mrdtable.attrname + possibletypes = [{} for _ in args] + any_type_is_ok = [False for _ in args] + def generate(node, level=0): + # this generates type-checking code like the following: + # + # _argtypenum = arg1.__typenum + # if _argtypenum == 5: + # ... + # elif _argtypenum == 6 or _argtypenum == 8: + # ... + # else: + # _failedtoimplement = True + # + # or, in the common particular case of an "anti-range", we optimize it to: + # + # _argtypenum = arg1.__typenum + # if _argtypenum < 5 or _argtypenum >= 10: + # ... + # else: + # _failedtoimplement = True + # + result = [] indent = ' '*level if node is True: + for i in range(level, len(args)): + any_type_is_ok[i] = True result.append('%s_failedtoimplement = False' % (indent,)) - return + return result if not node: result.append('%s_failedtoimplement = True' % (indent,)) - return - keyword = 'if' + return result + result.append('%s_argtypenum = %s.%s' % (indent, args[level], + attrname)) + cases = {} for key, subnode in node.items(): - typename = invent_name(self.miniglobals, key) - result.append('%s%s isinstance(%s, %s):' % (indent, keyword, - args[level], - typename)) - generate(subnode, level+1) + possibletypes[level][key] = True + casebody = tuple(generate(subnode, level+1)) + typenum = mrdtable.get_typenum(key) + cases.setdefault(casebody, []).append(typenum) + for casebody, typenums in cases.items(): + typenums.sort() + cases = [(typenums, casebody) + for (casebody, typenums) in cases.items()] + cases.sort() + if len(cases) == 1: + typenums, casebody = cases[0] + a, b = mrdtable.is_anti_range(typenums) + else: + a, b = None, None + keyword = 'if' + for typenums, casebody in cases: + if a is not None: + if b - a == 1: + condition = '_argtypenum != %d' % a + elif b == a: + condition = 'True' + else: + condition = '_argtypenum < %d or _argtypenum >= %d' % ( + a, b) + else: + conditions = ['_argtypenum == %d' % typenum + for typenum in typenums] + condition = ' or '.join(conditions) + result.append('%s%s %s:' % (indent, keyword, condition)) + result.extend(casebody) keyword = 'elif' result.append('%selse:' % (indent,)) result.append('%s _failedtoimplement = True' % (indent,)) + return result result = [] if self.typetree is not True: - generate(self.typetree) + result.extend(generate(self.typetree)) result.append('if _failedtoimplement:') result.append(' raise FailedToImplement') + for level in range(len(args)): + if not any_type_is_ok[level]: + cls = commonbase(possibletypes[level].keys()) + clsname = invent_name(self.miniglobals, cls) + result.append('assert isinstance(%s, %s)' % (args[level], + clsname)) return result +def commonbase(classlist): + def baseclasses(cls): + result = set([cls]) + for base in cls.__bases__: + if '_mixin_' not in base.__dict__: + result |= baseclasses(base) + return result + + bag = baseclasses(classlist[0]) + for cls in classlist[1:]: + bag &= baseclasses(cls) + _, candidate = max([(len(cls.__mro__), cls) for cls in bag]) + for cls in bag: + assert issubclass(candidate, cls) + return candidate + + class InstallerVersion2(object): """NOT_RPYTHON""" @@ -730,7 +801,9 @@ assert t1 in base_typeorder lst = list(base_typeorder) - lst.sort() + def clskey(cls): + return cls.__mro__[::-1] + lst.sort(lambda cls1, cls2: cmp(clskey(cls1), clskey(cls2))) key = tuple(lst) try: self.mrdtable = self.mrdtables[key] Modified: pypy/dist/pypy/objspace/std/test/test_multimethod.py ============================================================================== --- pypy/dist/pypy/objspace/std/test/test_multimethod.py (original) +++ pypy/dist/pypy/objspace/std/test/test_multimethod.py Tue May 20 12:50:54 2008 @@ -142,6 +142,29 @@ raises(FailedToImplement, mul2, 'baz', W_IntObject(), UserW_StringObject()) + def test_more_forbidden_subclasses(self): + mul = multimethod.MultiMethodTable(2, root_class=W_Root, + argnames_before=['space']) + class UserW_StringObject(W_StringObject): + pass + def mul__String_String(space, w_x, w_y): + assert space == 'space' + assert isinstance(w_x, W_StringObject) + assert isinstance(w_y, W_StringObject) + return 'fine' + mul.register(mul__String_String, W_StringObject, W_StringObject) + + ext_typeorder = {W_StringObject: [(W_StringObject, None)], + UserW_StringObject: []} + mul2 = mul.install('__mul2', [ext_typeorder, ext_typeorder]) + assert mul2('space', W_StringObject(), W_StringObject()) == 'fine' + raises(FailedToImplement, + mul2, 'baz', W_StringObject(), UserW_StringObject()) + raises(FailedToImplement, + mul2, 'baz', UserW_StringObject(), W_StringObject()) + raises(FailedToImplement, + mul2, 'baz', UserW_StringObject(), UserW_StringObject()) + def test_ANY(self): setattr = multimethod.MultiMethodTable(3, root_class=W_Root, argnames_before=['space']) From arigo at codespeak.net Tue May 20 13:10:45 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 20 May 2008 13:10:45 +0200 (CEST) Subject: [pypy-svn] r54990 - in pypy/branch/hybrid-io/pypy/rpython/memory: . gc gc/test gctransform Message-ID: <20080520111045.BA2E5168509@codespeak.net> Author: arigo Date: Tue May 20 13:10:44 2008 New Revision: 54990 Modified: pypy/branch/hybrid-io/pypy/rpython/memory/gc/base.py pypy/branch/hybrid-io/pypy/rpython/memory/gc/generation.py pypy/branch/hybrid-io/pypy/rpython/memory/gc/test/test_direct.py pypy/branch/hybrid-io/pypy/rpython/memory/gctransform/framework.py pypy/branch/hybrid-io/pypy/rpython/memory/gcwrapper.py Log: In-progress. Remove the "oldvalue" argument to write_barrier(). It's not used and it's annoying for the realloc operation. Modified: pypy/branch/hybrid-io/pypy/rpython/memory/gc/base.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/memory/gc/base.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/memory/gc/base.py Tue May 20 13:10:44 2008 @@ -42,7 +42,7 @@ def set_root_walker(self, root_walker): self.root_walker = root_walker - def write_barrier(self, oldvalue, newvalue, addr_struct): + def write_barrier(self, newvalue, addr_struct): pass def setup(self): Modified: pypy/branch/hybrid-io/pypy/rpython/memory/gc/generation.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/memory/gc/generation.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/memory/gc/generation.py Tue May 20 13:10:44 2008 @@ -408,7 +408,7 @@ continue # no need to remember this weakref any longer self.objects_with_weakrefs.append(obj) - def write_barrier(self, oldvalue, newvalue, addr_struct): + def write_barrier(self, newvalue, addr_struct): if self.header(addr_struct).tid & GCFLAG_NO_YOUNG_PTRS: self.remember_young_pointer(addr_struct, newvalue) Modified: pypy/branch/hybrid-io/pypy/rpython/memory/gc/test/test_direct.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/memory/gc/test/test_direct.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/memory/gc/test/test_direct.py Tue May 20 13:10:44 2008 @@ -78,18 +78,16 @@ def write(self, p, fieldname, newvalue): if self.gc.needs_write_barrier: - oldaddr = llmemory.cast_ptr_to_adr(getattr(p, fieldname)) newaddr = llmemory.cast_ptr_to_adr(newvalue) addr_struct = llmemory.cast_ptr_to_adr(p) - self.gc.write_barrier(oldaddr, newaddr, addr_struct) + self.gc.write_barrier(newaddr, addr_struct) setattr(p, fieldname, newvalue) def writearray(self, p, index, newvalue): if self.gc.needs_write_barrier: - oldaddr = llmemory.cast_ptr_to_adr(p[index]) newaddr = llmemory.cast_ptr_to_adr(newvalue) addr_struct = llmemory.cast_ptr_to_adr(p) - self.gc.write_barrier(oldaddr, newaddr, addr_struct) + self.gc.write_barrier(newaddr, addr_struct) p[index] = newvalue def malloc(self, TYPE, n=None): Modified: pypy/branch/hybrid-io/pypy/rpython/memory/gctransform/framework.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/memory/gctransform/framework.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/memory/gctransform/framework.py Tue May 20 13:10:44 2008 @@ -318,7 +318,7 @@ if GCClass.needs_write_barrier: self.write_barrier_ptr = getfn(GCClass.write_barrier.im_func, - [s_gc, annmodel.SomeAddress(), + [s_gc, annmodel.SomeAddress(), annmodel.SomeAddress()], annmodel.s_None, @@ -536,6 +536,7 @@ c_itemsize, c_lengthofs, c_grow): vlist = [self.realloc_ptr, self.c_const_gc, v_ptr, v_newsize, c_const_size, c_itemsize, c_lengthofs, c_grow] + # XXX don't really need push_roots in all cases livevars = self.push_roots(hop) v_result = hop.genop('direct_call', vlist, resulttype=llmemory.GCREF) @@ -672,18 +673,12 @@ and v_struct.concretetype.TO._gckind == "gc" and hop.spaceop not in self.initializing_stores): self.write_barrier_calls += 1 - v_oldvalue = hop.genop('g' + opname[1:], - hop.inputargs()[:-1], - resulttype=v_newvalue.concretetype) - v_oldvalue = hop.genop("cast_ptr_to_adr", [v_oldvalue], - resulttype = llmemory.Address) v_newvalue = hop.genop("cast_ptr_to_adr", [v_newvalue], resulttype = llmemory.Address) v_structaddr = hop.genop("cast_ptr_to_adr", [v_struct], resulttype = llmemory.Address) hop.genop("direct_call", [self.write_barrier_ptr, self.c_const_gc, - v_oldvalue, v_newvalue, v_structaddr]) hop.rename('bare_' + opname) Modified: pypy/branch/hybrid-io/pypy/rpython/memory/gcwrapper.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/memory/gcwrapper.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/memory/gcwrapper.py Tue May 20 13:10:44 2008 @@ -95,9 +95,7 @@ def setinterior(self, toplevelcontainer, inneraddr, INNERTYPE, newvalue): if (lltype.typeOf(toplevelcontainer).TO._gckind == 'gc' and isinstance(INNERTYPE, lltype.Ptr) and INNERTYPE.TO._gckind == 'gc'): - oldvalue = inneraddr.address[0] - self.gc.write_barrier(oldvalue, - llmemory.cast_ptr_to_adr(newvalue), + self.gc.write_barrier(llmemory.cast_ptr_to_adr(newvalue), llmemory.cast_ptr_to_adr(toplevelcontainer)) llheap.setinterior(toplevelcontainer, inneraddr, INNERTYPE, newvalue) From cfbolz at codespeak.net Tue May 20 13:17:21 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 20 May 2008 13:17:21 +0200 (CEST) Subject: [pypy-svn] r54991 - pypy/branch/gameboy-emulator Message-ID: <20080520111721.42A8A168509@codespeak.net> Author: cfbolz Date: Tue May 20 13:17:20 2008 New Revision: 54991 Removed: pypy/branch/gameboy-emulator/ Log: kill merged branch From fijal at codespeak.net Tue May 20 13:26:48 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 20 May 2008 13:26:48 +0200 (CEST) Subject: [pypy-svn] r54992 - pypy/branch/hybrid-io/pypy/rpython/memory/gc Message-ID: <20080520112648.6E3B416850D@codespeak.net> Author: fijal Date: Tue May 20 13:26:46 2008 New Revision: 54992 Modified: pypy/branch/hybrid-io/pypy/rpython/memory/gc/hybrid.py Log: (arigo, fijal) Delete old stack object. Modified: pypy/branch/hybrid-io/pypy/rpython/memory/gc/hybrid.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/memory/gc/hybrid.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/memory/gc/hybrid.py Tue May 20 13:26:46 2008 @@ -252,6 +252,7 @@ obj = objects.pop() if obj != addr: newstack.append(obj) + objects.delete() self.gen_resizable_objects = newstack def can_move(self, addr): From arigo at codespeak.net Tue May 20 14:28:21 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 20 May 2008 14:28:21 +0200 (CEST) Subject: [pypy-svn] r54994 - in pypy/branch/hybrid-io/pypy/rpython: lltypesystem memory/gc memory/gctransform Message-ID: <20080520122821.C206416853F@codespeak.net> Author: arigo Date: Tue May 20 14:28:20 2008 New Revision: 54994 Modified: pypy/branch/hybrid-io/pypy/rpython/lltypesystem/lloperation.py pypy/branch/hybrid-io/pypy/rpython/memory/gc/hybrid.py pypy/branch/hybrid-io/pypy/rpython/memory/gctransform/framework.py Log: (fijal, arigo) - Some renaming, some overflow checking, some other minor stuff. - Collect unreachable resizable objects during a generation 2 collect. Modified: pypy/branch/hybrid-io/pypy/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/lltypesystem/lloperation.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/lltypesystem/lloperation.py Tue May 20 14:28:20 2008 @@ -326,8 +326,8 @@ 'malloc_nonmovable': LLOp(canraise=(MemoryError,), canunwindgc=True), 'malloc_nonmovable_varsize':LLOp(canraise=(MemoryError,),canunwindgc=True), 'malloc_resizable_buffer': LLOp(canraise=(MemoryError,),canunwindgc=True), - 'resize_buffer': LLOp(canraise=(MemoryError,),canunwindgc=True), - 'finish_building_buffer' : LLOp(), + 'resize_buffer': LLOp(canraise=(MemoryError,)), + 'finish_building_buffer' : LLOp(canraise=(MemoryError,), canunwindgc=True), 'zero_gc_pointers_inside': LLOp(), 'free': LLOp(), 'getfield': LLOp(sideeffects=False, canrun=True), Modified: pypy/branch/hybrid-io/pypy/rpython/memory/gc/hybrid.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/memory/gc/hybrid.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/memory/gc/hybrid.py Tue May 20 14:28:20 2008 @@ -30,7 +30,7 @@ # Object lists: # * gen2_rawmalloced_objects # * gen3_rawmalloced_objects -# * gen_resizable_objects +# * gen2_resizable_objects # * old_objects_pointing_to_young: gen2or3 objs that point to gen1 objs # * last_generation_root_objects: gen3 objs that point to gen1or2 objs # @@ -43,12 +43,14 @@ # Some invariants: # * gen3 are either GCFLAG_NO_HEAP_PTRS or in 'last_generation_root_objects' # * between collections, GCFLAG_UNVISITED set exactly for gen2_rawmalloced +# * objects in gen2_resizable_objects are part of the generation 2 but never +# explicitly listed in gen2_rawmalloced_objects. # # A malloc_varsize() of large objects returns objects that are external # but initially of generation 2. Old objects from the semispaces are # moved to external objects directly as generation 3. -# gen_resizable objects is for objects that are resizable +# gen2_resizable_objects is for objects that are resizable # The "age" of an object is the number of times it survived a full # collections, without counting the step that moved it out of the nursery. @@ -121,7 +123,7 @@ def setup(self): self.gen2_rawmalloced_objects = self.AddressStack() self.gen3_rawmalloced_objects = self.AddressStack() - self.gen_resizable_objects = self.AddressStack() + self.gen2_resizable_objects = self.AddressStack() GenerationGC.setup(self) def set_max_heap_size(self, size): @@ -174,7 +176,7 @@ llmemory.GCREF) return self.malloc_varsize_slowpath(typeid, length) - def malloc_varsize_slowpath(self, typeid, length, force_old=False, + def malloc_varsize_slowpath(self, typeid, length, force_nonmovable=False, resizable=False): # For objects that are too large, or when the nursery is exhausted. # In order to keep malloc_varsize_clear() as compact as possible, @@ -193,7 +195,7 @@ nonlarge_max = self.nonlarge_gcptrs_max else: nonlarge_max = self.nonlarge_max - if force_old or raw_malloc_usage(totalsize) > nonlarge_max: + if force_nonmovable or raw_malloc_usage(totalsize) > nonlarge_max: result = self.malloc_varsize_marknsweep(totalsize, resizable) flags = self.GCFLAGS_FOR_NEW_EXTERNAL_OBJECTS | GCFLAG_UNVISITED else: @@ -204,7 +206,6 @@ return llmemory.cast_adr_to_ptr(result+size_gc_header, llmemory.GCREF) malloc_varsize_slowpath._dont_inline_ = True - malloc_varsize_slowpath._annspecialcase_ = 'specialize:arg(3, 4)' def malloc_varsize_nonmovable(self, typeid, length): return self.malloc_varsize_slowpath(typeid, length, True) @@ -220,13 +221,18 @@ raise NotImplementedError("Not supported") return llmemory.cast_ptr_to_adr(gcref) - def realloc(self, ptr, newsize, const_size, itemsize, lengthofs, grow): + def realloc(self, ptr, newlength, fixedsize, itemsize, lengthofs, grow): size_gc_header = self.size_gc_header() addr = llmemory.cast_ptr_to_adr(ptr) tid = self.get_type_id(addr) - tot_size = size_gc_header + const_size + newsize * itemsize - oldsize = (addr + lengthofs).signed[0] - old_tot_size = size_gc_header + const_size + oldsize * itemsize + nonvarsize = size_gc_header + fixedsize + try: + varsize = ovfcheck(itemsize * newlength) + tot_size = ovfcheck(nonvarsize + varsize) + except OverflowError: + raise MemoryError() + oldlength = (addr + lengthofs).signed[0] + old_tot_size = size_gc_header + fixedsize + oldlength * itemsize source_addr = addr - size_gc_header self._remove_addr_from_resizable_objects(addr) if grow: @@ -236,24 +242,27 @@ result = llop.raw_realloc_shrink(llmemory.Address, source_addr, old_tot_size, tot_size) if not result: + self.gen2_resizable_objects.append(addr) raise MemoryError() if grow: - self.gen_resizable_objects.append(result + size_gc_header) + self.gen2_resizable_objects.append(result + size_gc_header) else: self.gen2_rawmalloced_objects.append(result + size_gc_header) - self._check_rawsize_alloced(tot_size) - (result + size_gc_header + lengthofs).signed[0] = newsize + self._check_rawsize_alloced(raw_malloc_usage(tot_size) - + raw_malloc_usage(old_tot_size), + can_collect = not grow) + (result + size_gc_header + lengthofs).signed[0] = newlength return llmemory.cast_adr_to_ptr(result + size_gc_header, llmemory.GCREF) def _remove_addr_from_resizable_objects(self, addr): - objects = self.gen_resizable_objects + objects = self.gen2_resizable_objects newstack = self.AddressStack() while objects.non_empty(): obj = objects.pop() if obj != addr: newstack.append(obj) objects.delete() - self.gen_resizable_objects = newstack + self.gen2_resizable_objects = newstack def can_move(self, addr): tid = self.header(addr).tid @@ -268,9 +277,9 @@ totalsize) return result - def _check_rawsize_alloced(self, totalsize): - self.large_objects_collect_trigger -= raw_malloc_usage(totalsize) - if self.large_objects_collect_trigger < 0: + def _check_rawsize_alloced(self, size_estimate, can_collect=True): + self.large_objects_collect_trigger -= size_estimate + if can_collect and self.large_objects_collect_trigger < 0: if DEBUG_PRINT: llop.debug_print(lltype.Void, "allocated", self._initial_trigger - @@ -286,7 +295,7 @@ # XXX and adjust sizes based on it; otherwise we risk doing # XXX many many collections if the program allocates a lot # XXX more than the current self.space_size. - self._check_rawsize_alloced(totalsize) + self._check_rawsize_alloced(raw_malloc_usage(totalsize)) result = self.allocate_external_object(totalsize) if not result: raise MemoryError() @@ -295,11 +304,10 @@ llmemory.raw_memclear(result, totalsize) size_gc_header = self.gcheaderbuilder.size_gc_header if resizable: - self.gen_resizable_objects.append(result + size_gc_header) + self.gen2_resizable_objects.append(result + size_gc_header) else: self.gen2_rawmalloced_objects.append(result + size_gc_header) return result - malloc_varsize_marknsweep._annspecialcase_ = 'specialize:arg(2)' def allocate_external_object(self, totalsize): # XXX maybe we should use arena_malloc() above a certain size? @@ -455,6 +463,7 @@ if self.is_collecting_gen3(): self.sweep_rawmalloced_objects(generation=3) self.sweep_rawmalloced_objects(generation=2) + self.sweep_rawmalloced_objects(generation=-2) # As we just collected, it's fine to raw_malloc'ate up to space_size # bytes again before we should force another collect. self.large_objects_collect_trigger = self.space_size @@ -473,7 +482,7 @@ # to any gen2 object. In this case, A remains a bit too long in # last_generation_root_objects, but this will be fixed by the # next collect_last_generation_roots(). - else: + elif generation == 3: objects = self.gen3_rawmalloced_objects # generation 3 sweep: remove from last_generation_root_objects # all the objects that we are about to free @@ -485,6 +494,11 @@ newgen3roots.append(obj) gen3roots.delete() self.last_generation_root_objects = newgen3roots + else: + # mostly a hack: the generation number -2 is the part of the + # generation 2 that lives in gen2_resizable_objects + ll_assert(generation == -2, "bogus 'generation'") + objects = self.gen2_resizable_objects surviving_objects = self.AddressStack() if DEBUG_PRINT: alive_count = alive_size = 0 @@ -502,7 +516,7 @@ if DEBUG_PRINT:alive_size+=raw_malloc_usage(self.get_size(obj)) if generation == 3: surviving_objects.append(obj) - else: + elif generation == 2: ll_assert((tid & GCFLAG_AGE_MASK) < GCFLAG_AGE_MAX, "wrong age for generation 2 object") tid += GCFLAG_AGE_ONE @@ -516,11 +530,18 @@ tid |= GCFLAG_UNVISITED surviving_objects.append(obj) self.header(obj).tid = tid + elif generation == -2: + # the object stays in generation -2 + tid |= GCFLAG_UNVISITED + surviving_objects.append(obj) + self.header(obj).tid = tid objects.delete() if generation == 2: self.gen2_rawmalloced_objects = surviving_objects - else: + elif generation == 3: self.gen3_rawmalloced_objects = surviving_objects + elif generation == -2: + self.gen2_resizable_objects = surviving_objects if DEBUG_PRINT: llop.debug_print(lltype.Void, "| [hyb] gen", generation, Modified: pypy/branch/hybrid-io/pypy/rpython/memory/gctransform/framework.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/memory/gctransform/framework.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/memory/gctransform/framework.py Tue May 20 14:28:20 2008 @@ -536,8 +536,10 @@ c_itemsize, c_lengthofs, c_grow): vlist = [self.realloc_ptr, self.c_const_gc, v_ptr, v_newsize, c_const_size, c_itemsize, c_lengthofs, c_grow] - # XXX don't really need push_roots in all cases - livevars = self.push_roots(hop) + if c_grow.value: + livevars = [] # collection not possible if grow=True + else: + livevars = self.push_roots(hop) v_result = hop.genop('direct_call', vlist, resulttype=llmemory.GCREF) self.pop_roots(hop, livevars) From hpk at codespeak.net Tue May 20 14:29:41 2008 From: hpk at codespeak.net (hpk at codespeak.net) Date: Tue, 20 May 2008 14:29:41 +0200 (CEST) Subject: [pypy-svn] r54995 - pypy/django/tests Message-ID: <20080520122941.040DB168546@codespeak.net> Author: hpk Date: Tue May 20 14:29:41 2008 New Revision: 54995 Modified: pypy/django/tests/conftest.py Log: (anto, hpk) hack until unit tests work more or less Modified: pypy/django/tests/conftest.py ============================================================================== --- pypy/django/tests/conftest.py (original) +++ pypy/django/tests/conftest.py Tue May 20 14:29:41 2008 @@ -11,9 +11,7 @@ DIRNAMES = ['modeltests', 'regressiontests']#, 'django/contrib'] -import py.__.test.compat import unittest -unittest.TestCase = py.__.test.compat.TestCase class DocTestItem(py.test.collect.Item): @@ -47,7 +45,6 @@ py.test.fail("doctest %s: %s failed out of %s" %( self.fspath, runner.failures, runner.tries)) - loaded_apps = {} class DjangoTestModule(py.test.collect.Module): @@ -65,15 +62,22 @@ def _tests_from_mod(self, mod): result = [] - #if hasattr(mod, 'suite'): - # import pdb - # pdb.set_trace() - #else: - # items = [k for k, v in - # mod.__dict__.iteritems() - # if isinstance(v, type) and - # issubclass(v, unittest.TestCase)] - # result += items + if hasattr(mod, 'suite'): + s = mod.suite() + namemethods = getmethods2(s) + meth = [] + for method in namemethods: + name = (method.__class__.__name__ + '.' + + method._TestCase__testMethodName) + meth.append(name) + result += meth + else: + meth = [] + for name, obj in vars(mod).items(): + if isinstance(obj, type) and issubclass(obj, unittest.TestCase): + namemethods = getmethodnames(obj) + meth.extend(namemethods) + result += meth result += self._find_doctests(mod) return result @@ -106,10 +110,26 @@ mod = mod.tests return DocTestItem(self.fspath.basename + '.%docstring%', mod, mod.__test__['API_TESTS']) elif name.startswith('tests'): - return getattr(mod.tests, name[len('tests.'):]) + return DjangoUnitTest(name, self) else: - return getattr(mod, name) + return DjangoUnitTest(name, self) +class DjangoUnitTest(py.test.collect.Item): + def run(self): + names = self.name.split(".") + mod = self.parent._get_mod() + if names[0] == "tests": + assert len(names) == 3 + names.pop(0) + mod = getattr(mod, "tests") + else: + assert len(names) == 2 + #import pdb + #pdb.set_trace() + testcasecls = getattr(mod, names[0]) + testcase = testcasecls(names[1]) + run_testcase_method(testcase) + class DjangoTestDirectory(py.test.collect.Directory): def _level(self): rel = self.fspath.relto(rootdir) @@ -194,3 +214,42 @@ Directory = DjangoTestDirectory Module = DjangoTestModule + +# the below taken from pypy/lib-python/conftest.py + +def getmethodnames(cls): + l = [] + for name, obj in vars(cls).items(): + if name.startswith("test"): + l.append("%s.%s" %(cls.__name__, name)) + return l + +def getmethods2(suite_or_class): + """ flatten out suites down to TestCase instances/methods. """ + if isinstance(suite_or_class, unittest.TestCase): + res = [suite_or_class] + elif isinstance(suite_or_class, unittest.TestSuite): + res = [] + for x in suite_or_class._tests: + res.extend(getmethods2(x)) + elif isinstance(suite_or_class, list): + res = [] + for x in suite_or_class: + res.extend(getmethods2(x)) + else: + raise TypeError, "expected TestSuite or TestClass, got %r" %(suite_or_class) + return res + + + +def run_testcase_method(method): + result = method.defaultTestResult() + method.run(result) + if result.errors: + assert len(result.errors) + print result.errors[0][1] + if result.failures: + assert len(result.failures) + print result.failures[0][1] + if result.failures or result.errors: + return 1 From pedronis at codespeak.net Tue May 20 15:35:22 2008 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 20 May 2008 15:35:22 +0200 (CEST) Subject: [pypy-svn] r54996 - pypy/django/tests Message-ID: <20080520133522.3844516842A@codespeak.net> Author: pedronis Date: Tue May 20 15:35:20 2008 New Revision: 54996 Modified: pypy/django/tests/conftest.py Log: note about django contrib tests not run for now Modified: pypy/django/tests/conftest.py ============================================================================== --- pypy/django/tests/conftest.py (original) +++ pypy/django/tests/conftest.py Tue May 20 15:35:20 2008 @@ -3,6 +3,7 @@ import os # XXX ignores invalid models path +# XXX no django/contrib rootdir = py.path.local(__file__).dirpath() pkgroot = rootdir.dirpath() From tverwaes at codespeak.net Tue May 20 15:54:49 2008 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Tue, 20 May 2008 15:54:49 +0200 (CEST) Subject: [pypy-svn] r54997 - in pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk: . test Message-ID: <20080520135449.754881684EC@codespeak.net> Author: tverwaes Date: Tue May 20 15:54:47 2008 New Revision: 54997 Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/classtable.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/interpreter.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/objtable.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_model.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_primitives.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_shadow.py Log: (cfbolz, tverwaes) making all current tests work with new style of contextshadows Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/classtable.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/classtable.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/classtable.py Tue May 20 15:54:47 2008 @@ -1,21 +1,23 @@ from pypy.lang.smalltalk import shadow, constants from pypy.lang.smalltalk import constants +from pypy.rlib.objectmodel import instantiate def bootstrap_class(instsize, w_superclass=None, w_metaclass=None, name='?', format=shadow.POINTERS, varsized=False): from pypy.lang.smalltalk import model w_class = model.W_PointersObject(w_metaclass, 0) # a dummy placeholder for testing - s = shadow.ClassShadow(w_class, True) - s.methoddict = {} - if w_superclass is not None: - s.w_superclass = w_superclass + # XXX + s = instantiate(shadow.ClassShadow) + s._w_self = w_class + s.w_superclass = w_superclass s.name = name s.instance_size = instsize s.instance_kind = format + s.w_methoddict = None s.instance_varsized = varsized or format != shadow.POINTERS s.invalid = False - w_class._shadow = s + w_class.store_shadow(s) return w_class # ___________________________________________________________________________ @@ -65,8 +67,11 @@ define_core_cls(cls_nm, classtable[super_cls_nm], w_metacls) w_Class = classtable["w_Class"] w_Metaclass = classtable["w_Metaclass"] - w_ProtoObjectClass.as_class_get_shadow().w_superclass = \ - w_Class + # XXX + proto_shadow = instantiate(shadow.ClassShadow) + proto_shadow.invalid = False + proto_shadow.w_superclass = w_Class + w_ProtoObjectClass.store_shadow(proto_shadow) # at this point, all classes that still lack a w_class are themselves # metaclasses for nm, w_cls_obj in classtable.items(): Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/interpreter.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/interpreter.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/interpreter.py Tue May 20 15:54:47 2008 @@ -69,7 +69,7 @@ cnt += 1 # Do not update the context # for this action. - p = p.as_context_get_shadow(False).w_sender() + p = p.as_context_get_shadow().w_sender() self._last_indent = " " * cnt self._w_last_active_context = self.w_active_context() Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py Tue May 20 15:54:47 2008 @@ -262,20 +262,25 @@ # XXX XXX # Find better way of overloading shadows... - def setshadow(self, shadow): + def store_shadow(self, shadow): self._shadow = shadow @objectmodel.specialize.arg(1) - def as_special_get_shadow(self, TheClass, invalid=True): + def attach_shadow_of_class(self, TheClass): + shadow = TheClass(self) + self._shadow = shadow + shadow.attach_shadow() + return shadow + + @objectmodel.specialize.arg(1) + def as_special_get_shadow(self, TheClass): shadow = self._shadow if shadow is None: - shadow = TheClass(self, invalid) - self._shadow = shadow + shadow = self.attach_shadow_of_class(TheClass) elif not isinstance(shadow, TheClass): shadow.sync_w_self() shadow.invalidate_shadow() - shadow = TheClass(self, invalid) - self._shadow = shadow + shadow = self.attach_shadow_of_class(TheClass) shadow.sync_shadow() return shadow @@ -287,19 +292,19 @@ from pypy.lang.smalltalk.shadow import ClassShadow return self.as_special_get_shadow(ClassShadow) - def as_blockcontext_get_shadow(self, invalid=True): + def as_blockcontext_get_shadow(self): from pypy.lang.smalltalk.shadow import BlockContextShadow - return self.as_special_get_shadow(BlockContextShadow, invalid) + return self.as_special_get_shadow(BlockContextShadow) - def as_methodcontext_get_shadow(self, invalid=True): + def as_methodcontext_get_shadow(self): from pypy.lang.smalltalk.shadow import MethodContextShadow - return self.as_special_get_shadow(MethodContextShadow, invalid) + return self.as_special_get_shadow(MethodContextShadow) - def as_context_get_shadow(self, invalid=True): + def as_context_get_shadow(self): from pypy.lang.smalltalk.shadow import ContextPartShadow # XXX TODO should figure out itself if its method or block context assert self._shadow is not None - return self.as_special_get_shadow(ContextPartShadow, invalid) + return self.as_special_get_shadow(ContextPartShadow) def as_methoddict_get_shadow(self): from pypy.lang.smalltalk.shadow import MethodDictionaryShadow @@ -554,34 +559,41 @@ def W_BlockContext(w_home, w_sender, argcnt, initialip): from pypy.lang.smalltalk.classtable import w_BlockContext + from pypy.lang.smalltalk import shadow + # create and attach a shadow manually, to not have to carefully put things + # into the right places in the W_PointersObject + # XXX could hack some more to never have to create the _vars of w_result w_result = W_PointersObject(w_BlockContext, w_home.size()) - # Only home-brewed shadows are not invalid from start. - s_result = w_result.as_blockcontext_get_shadow(invalid=False) + s_result = shadow.BlockContextShadow(w_result) + w_result._shadow = s_result s_result.store_expected_argument_count(argcnt) s_result.store_initialip(initialip) s_result.store_w_home(w_home) - s_result._stack = [] - s_result._pc = initialip + s_result.store_pc(initialip) return w_result def W_MethodContext(w_method, w_receiver, arguments, w_sender=None): from pypy.lang.smalltalk.classtable import w_MethodContext + from pypy.lang.smalltalk import objtable, shadow # From blue book: normal mc have place for 12 temps+maxstack # mc for methods with islarge flag turned on 32 size = 12 + w_method.islarge * 20 + w_method.argsize w_result = w_MethodContext.as_class_get_shadow().new(size) assert isinstance(w_result, W_PointersObject) - # Only home-brewed shadows are not invalid from start. - s_result = w_result.as_methodcontext_get_shadow(invalid=False) + # create and attach a shadow manually, to not have to carefully put things + # into the right places in the W_PointersObject + # XXX could hack some more to never have to create the _vars of w_result + s_result = shadow.MethodContextShadow(w_result) + w_result._shadow = s_result s_result.store_w_method(w_method) if w_sender: s_result.store_w_sender(w_sender) s_result.store_w_receiver(w_receiver) s_result.store_pc(0) + s_result._temps = [objtable.w_nil] * w_method.tempframesize() for i in range(len(arguments)): s_result.settemp(i, arguments[i]) - s_result._stack = [] return w_result # Use black magic to create w_nil without running the constructor, Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/objtable.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/objtable.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/objtable.py Tue May 20 15:54:47 2008 @@ -5,6 +5,7 @@ # ___________________________________________________________________________ # Global Data + def wrap_char_table(): global w_charactertable def bld_char(i): @@ -18,12 +19,6 @@ wrap_char_table() -w_true = classtable.classtable['w_True'].as_class_get_shadow().new() -w_false = classtable.classtable['w_False'].as_class_get_shadow().new() -w_minus_one = model.W_SmallInteger(-1) -w_zero = model.W_SmallInteger(0) -w_one = model.W_SmallInteger(1) -w_two = model.W_SmallInteger(2) # Very special nil hack: in order to allow W_PointersObject's to # initialize their fields to nil, we have to create it in the model @@ -31,6 +26,13 @@ w_nil = model.w_nil w_nil.w_class = classtable.classtable['w_UndefinedObject'] +w_true = classtable.classtable['w_True'].as_class_get_shadow().new() +w_false = classtable.classtable['w_False'].as_class_get_shadow().new() +w_minus_one = model.W_SmallInteger(-1) +w_zero = model.W_SmallInteger(0) +w_one = model.W_SmallInteger(1) +w_two = model.W_SmallInteger(2) + # We use indirection because translated globals are assumed to be constant class ObjectTableHolder(object): pass Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py Tue May 20 15:54:47 2008 @@ -16,8 +16,9 @@ return self._w_self def getname(self): return repr(self) - def detach_shadow(self): - pass + def attach_shadow(self): pass + def detach_shadow(self): pass + def sync_shadow(self): pass class AbstractCachingShadow(AbstractShadow): def __init__(self, w_self): @@ -35,7 +36,7 @@ self.update_shadow() def update_shadow(self): - self.w_self().setshadow(self) + self.w_self().store_shadow(self) self.invalid = False self.sync_cache() @@ -66,7 +67,7 @@ (i.e. used as the class of another Smalltalk object). """ def invalidate_shadow(self): - AbstractShadow.invalidate_shadow(self) + AbstractCachingShadow.invalidate_shadow(self) self.w_methoddict = None self.w_superclass = None self.name = None @@ -75,10 +76,8 @@ return "%s class" % (self.name or '?',) def sync_cache(self): - from pypy.lang.smalltalk import objtable - + from pypy.lang.smalltalk.objtable import w_nil "Update the ClassShadow with data from the w_self class." - AbstractShadow.update_shadow(self) w_self = self.w_self() # read and painfully decode the format @@ -124,13 +123,11 @@ assert isinstance(self.w_methoddict, model.W_PointersObject) w_superclass = w_self._vars[constants.CLASS_SUPERCLASS_INDEX] - if w_superclass.is_same_object(objtable.w_nil): + if w_superclass.is_same_object(w_nil): self.w_superclass = None else: self.w_superclass = w_superclass - AbstractShadow.update_shadow(self) - def guess_class_name(self): w_self = self.w_self() w_name = None @@ -255,7 +252,8 @@ w_values = self.w_self()._vars[constants.METHODDICT_VALUES_INDEX] assert isinstance(w_values, model.W_PointersObject) s_values = w_values.get_shadow() - s_values.notifyinvalid(self) + # XXX Should add! + # s_values.notifyinvalid(self) size = self.w_self().size() - constants.METHODDICT_NAMES_INDEX self.methoddict = {} for i in range(size): @@ -280,64 +278,94 @@ def store(self, n0, w_value): raise NotImplementedError() + def attach_shadow(self): + AbstractShadow.attach_shadow(self) + for i in range(self._w_self_size): + self.copy_from_w_self(i) + + def detach_shadow(self): + self.w_self()._vars = [objtable.w_nil] * self._w_self_size + for i in range(self._w_self_size): + self.copy_to_w_self(i) + self.invalidate_shadow() + + def copy_from_w_self(self, n0): + self.store(n0, self.w_self()._fetch(n0)) + def copy_to_w_self(self, n0): + self.w_self()._store(n0, self.fetch(n0)) + class ContextPartShadow(AbstractRedirectingShadow): __metaclass__ = extendabletype + def __init__(self, w_self): + from pypy.lang.smalltalk import objtable + self._w_sender = objtable.w_nil + self._stack = [] + AbstractRedirectingShadow.__init__(self, w_self) + + # TODO test def fetch(self, n0): if n0 == constants.CTXPART_SENDER_INDEX: return self.w_sender() if n0 == constants.CTXPART_PC_INDEX: return self.wrap_pc() if n0 == constants.CTXPART_STACKP_INDEX: - return utility.wrap_int(self.stackpointer()) + return self.wrap_stackpointer() if self.stackstart() <= n0 < self.stackpointer(): return self._stack[n0-self.stackstart()] if self.stackpointer() <= n0 < self.stackend(): + from pypy.lang.smalltalk import objtable return objtable.w_nil else: # XXX later should store tail out of known context part as well raise error.WrapperException("Index in context out of bounds") + # TODO test def store(self, n0, w_value): if n0 == constants.CTXPART_SENDER_INDEX: return self.store_w_sender(w_value) if n0 == constants.CTXPART_PC_INDEX: return self.store_unwrap_pc(w_value) if n0 == constants.CTXPART_STACKP_INDEX: - return self.store_stackpointer(utility.unwrap_int(w_value)) + return self.unwrap_store_stackpointer(w_value) if self.stackstart() <= n0 < self.stackpointer(): - return self._stack[n0-self.stackstart()] = w_value + self._stack[n0 - self.stackstart()] = w_value + return if self.stackpointer() <= n0 < self.stackend(): - raise error.WrapperException( - "Trying to store within stack range, after actual stack") + return else: # XXX later should store tail out of known context part as well raise error.WrapperException("Index in context out of bounds") - def update_shadow(self): - # XXX We need the method before reading pc - # and stack (islarge -> stack + args + locals size) - AbstractShadow.update_shadow(self) - for i in range(self._w_self_size): - self.store(i, self.w_self()._fetch(i)) + def unwrap_store_stackpointer(self, w_sp1): + # the stackpointer in the W_PointersObject starts counting at the + # tempframe start + # Stackpointer from smalltalk world == stacksize in python world + self.store_stackpointer(utility.unwrap_int(w_sp1) - + self.w_method().tempframesize()) - def store_unwrap_pc(self, w_pc): - self._pc = utility.unwrap_int(w_pc) - self._pc -= self.w_method().bytecodeoffset() - self._pc -= 1 + # TODO test + def store_stackpointer(self, size): + from pypy.lang.smalltalk import objtable + if size < len(self._stack): + self._stack = self._stack[:size] + else: + add = [objtable.w_nil] * (size - len(self._stack)) + self._stack.extend(add) - def wrap_pc(self): - pc = self._pc - pc += 1 - pc += self.w_method().bytecodeoffset() - return utility.wrap_int(pc) + def wrap_stackpointer(self): + return utility.wrap_int(self.stackpointer() + 1) + + # TODO test + def stackpointer(self): + return self.stackstart() + len(self._stack) def w_home(self): raise NotImplementedError() def s_home(self): - raise NotImplementedError() + return self.w_home().as_methodcontext_get_shadow() def stackstart(self): raise NotImplementedError() @@ -349,10 +377,12 @@ " Return self of the method, or the method that contains the block " return self.s_home().w_receiver() + def store_w_sender(self, w_sender): + assert isinstance(w_sender, model.W_PointersObject) + self._w_sender = w_sender + def w_sender(self): - w_v = self.w_self()._vars[constants.CTXPART_SENDER_INDEX] - assert isinstance(w_v, model.W_PointersObject) - return w_v + return self._w_sender def s_sender(self): from pypy.lang.smalltalk import objtable @@ -362,8 +392,19 @@ else: return w_sender.as_context_get_shadow() - def store_w_sender(self, w_sender): - self.w_self()._vars[constants.CTXPART_SENDER_INDEX] = w_sender + # TODO test + def store_unwrap_pc(self, w_pc): + pc = utility.unwrap_int(w_pc) + pc -= self.w_method().bytecodeoffset() + pc -= 1 + self.store_pc(pc) + + # TODO test + def wrap_pc(self): + pc = self.pc() + pc += 1 + pc += self.w_method().bytecodeoffset() + return utility.wrap_int(pc) def pc(self): return self._pc @@ -371,16 +412,9 @@ def store_pc(self, newpc): self._pc = newpc - def stackpointer(self): - return (utility.unwrap_int(self.w_self()._vars[constants.CTXPART_STACKP_INDEX]) + - self.stackpointer_offset()) - def stackpointer_offset(self): raise NotImplementedError() - def store_stackpointer(self, pointer): - self.w_self()._vars[constants.CTXPART_STACKP_INDEX] = utility.wrap_int(pointer) - # ______________________________________________________________________ # Method that contains the bytecode for this method/block context @@ -412,17 +446,13 @@ # ______________________________________________________________________ # Stack Manipulation def pop(self): - w_v = self._stack[-1] - self._stack = self._stack[:-1] - return w_v + return self._stack.pop() def push(self, w_v): - self._stack += [w_v] + self._stack.append(w_v) def push_all(self, lst): - #for x in lst: - # self.push(x) - self._stack += lst + self._stack.extend(lst) def top(self): return self.peek(0) @@ -450,27 +480,48 @@ class BlockContextShadow(ContextPartShadow): def __init__(self, w_self): - self._s_home = None ContextPartShadow.__init__(self, w_self) - def invalidate_shadow(self): - if self._s_home is not None: - self._s_home.unnotify(self) - self._s_home = None - AbstractShadow.invalidate_shadow(self) + def fetch(self, n0): + if n0 == constants.BLKCTX_HOME_INDEX: + return self.w_home() + if n0 == constants.BLKCTX_INITIAL_IP_INDEX: + return self.wrap_initialip() + if n0 == constants.BLKCTX_BLOCK_ARGUMENT_COUNT_INDEX: + return self.wrap_eargc() + else: + return ContextPartShadow.fetch(self, n0) - def update_shadow(self): - self.store_w_home(self.w_self()._vars[constants.BLKCTX_HOME_INDEX]) - self._initialip = utility.unwrap_int(self.w_self()._vars[constants.BLKCTX_INITIAL_IP_INDEX]) - self._initialip -= 1 + self.w_method().getliteralsize() - self._eargc = utility.unwrap_int(self.w_self()._vars[constants.BLKCTX_BLOCK_ARGUMENT_COUNT_INDEX]) + def store(self, n0, w_value): + if n0 == constants.BLKCTX_HOME_INDEX: + return self.store_w_home(w_value) + if n0 == constants.BLKCTX_INITIAL_IP_INDEX: + return self.uwrap_store_initialip(w_value) + if n0 == constants.BLKCTX_BLOCK_ARGUMENT_COUNT_INDEX: + return self.unwrap_store_eargc(w_value) + else: + return ContextPartShadow.fetch(self, n0) + + def attach_shadow(self): + # Make sure the home context is updated first + self.copy_from_w_self(constants.BLKCTX_HOME_INDEX) ContextPartShadow.update_shadow(self) - def update_w_self(self): - ContextPartShadow.update_w_self(self) - self.w_self()._vars[constants.BLKCTX_INITIAL_IP_INDEX] = utility.wrap_int(self._initialip + 1 + self.w_method().getliteralsize()) - self.w_self()._vars[constants.BLKCTX_BLOCK_ARGUMENT_COUNT_INDEX] = utility.wrap_int(self._eargc) - self.w_self()._vars[constants.BLKCTX_HOME_INDEX] = self._w_home + def store_unwrap_initialip(self, w_value): + initialip = utility.unwrap_int(w_value) + initialip -= 1 + self.w_method().getliteralsize() + self.store_initialip(initialip) + + def wrap_initialip(self): + initialip = self.initialip() + initialip += 1 + self.w_method().getliteralsize() + return utility.wrap_int(initialip) + + def unwrap_store_eargc(self, w_value): + self.store_expected_argument_count(utility.unwrap_int(w_value)) + + def wrap_eargc(self): + return utility.wrap_int(self.expected_argument_count()) def expected_argument_count(self): return self._eargc @@ -485,21 +536,12 @@ self._initialip = initialip def store_w_home(self, w_home): - if self._s_home is not None: - self._s_home.unnotify(self) - self._s_home = None assert isinstance(w_home, model.W_PointersObject) self._w_home = w_home def w_home(self): return self._w_home - def s_home(self): - if self._s_home is None: - self._s_home = self._w_home.as_methodcontext_get_shadow() - self._s_home.notifyinvalid(self) - return self._s_home - def reset_stack(self): self._stack = [] @@ -510,17 +552,48 @@ return constants.BLKCTX_STACK_START class MethodContextShadow(ContextPartShadow): - def __init__(self, w_self, invalid): - ContextPartShadow.__init__(self, w_self, invalid) + def __init__(self, w_self): + from pypy.lang.smalltalk import objtable + self.w_receiver_map = objtable.w_nil + self._w_receiver = None + ContextPartShadow.__init__(self, w_self) - def update_shadow(self): - # Make sure the method is updated first - self.store_w_method(self.w_self()._vars[constants.MTHDCTX_METHOD]) - ContextPartShadow.update_shadow(self) + def fetch(self, n0): + if n0 == constants.MTHDCTX_METHOD: + return self.w_method() + if n0 == constants.MTHDCTX_RECEIVER_MAP: + return self.w_receiver_map + if n0 == constants.MTHDCTX_RECEIVER: + return self.w_receiver() + if (0 <= n0-constants.MTHDCTX_TEMP_FRAME_START < + self.w_method().tempframesize()): + return self.gettemp(n0-constants.MTHDCTX_TEMP_FRAME_START) + else: + return ContextPartShadow.fetch(self, n0) - def update_w_self(self): - ContextPartShadow.update_w_self(self) - self.w_self()._vars[constants.MTHDCTX_METHOD] = self._w_method + def store(self, n0, w_value): + if n0 == constants.MTHDCTX_METHOD: + return self.store_w_method(w_value) + if n0 == constants.MTHDCTX_RECEIVER_MAP: + self.w_receiver_map = w_value + return + if n0 == constants.MTHDCTX_RECEIVER: + self.store_w_receiver(w_value) + return + if (0 <= n0-constants.MTHDCTX_TEMP_FRAME_START < + self.w_method().tempframesize()): + return self.settemp(n0-constants.MTHDCTX_TEMP_FRAME_START, + w_value) + else: + return ContextPartShadow.store(self, n0, w_value) + + def attach_shadow(self): + from pypy.lang.smalltalk import objtable + # Make sure the method is updated first + self.copy_from_w_self(constants.MTHDCTX_METHOD) + # And that there is space for the temps + self._temps = [objtable.w_nil] * self.w_method().tempframesize() + ContextPartShadow.attach_shadow(self) def w_method(self): return self._w_method @@ -530,16 +603,16 @@ self._w_method = w_method def w_receiver(self): - return self.w_self()._vars[constants.MTHDCTX_RECEIVER] + return self._w_receiver def store_w_receiver(self, w_receiver): - self.w_self()._vars[constants.MTHDCTX_RECEIVER] = w_receiver + self._w_receiver = w_receiver def gettemp(self, index0): - return self.w_self()._vars[constants.MTHDCTX_TEMP_FRAME_START + index0] + return self._temps[index0] def settemp(self, index0, w_value): - self.w_self()._vars[constants.MTHDCTX_TEMP_FRAME_START + index0] = w_value + self._temps[index0] = w_value def w_home(self): return self.w_self() @@ -547,14 +620,13 @@ def s_home(self): return self - def store_stackpointer(self, pointer): - ContextPartShadow.store_stackpointer(self, - pointer+self.w_method().tempframesize()) - def stackpointer_offset(self): return constants.MTHDCTX_TEMP_FRAME_START def stackstart(self): - w_method = self.w_method() return (constants.MTHDCTX_TEMP_FRAME_START + - w_method.tempframesize()) + self.w_method().tempframesize()) + + def stackend(self): + # XXX this is incorrect when there is subclassing + return self._w_self_size Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_model.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_model.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_model.py Tue May 20 15:54:47 2008 @@ -67,7 +67,6 @@ assert shadow.lookup("foo") == 1 assert shadow.lookup("bar") == 2 py.test.raises(MethodNotFound, shadow.lookup, "zork") - print subshadow.methoddict assert subshadow.lookup("foo") == 3 assert subshadow.lookup("bar") == 2 py.test.raises(MethodNotFound, subshadow.lookup, "zork") Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_primitives.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_primitives.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_primitives.py Tue May 20 15:54:47 2008 @@ -12,9 +12,12 @@ class MockFrame(model.W_PointersObject): def __init__(self, stack): self._vars = [None] * 6 + stack - s_self = self.as_blockcontext_get_shadow(False) + s_self = self.as_blockcontext_get_shadow() s_self._stack = stack s_self.store_expected_argument_count(0) + def as_blockcontext_get_shadow(self): + self._shadow = shadow.BlockContextShadow(self) + return self._shadow def wrap(x): if isinstance(x, int): return utility.wrap_int(x) Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_shadow.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_shadow.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_shadow.py Tue May 20 15:54:47 2008 @@ -96,6 +96,7 @@ w_object = methodcontext(stackpointer=3, method=w_m) w_object2 = methodcontext(w_sender=w_object) s_object = w_object.as_methodcontext_get_shadow() + assert len(s_object.stack()) == 3 s_object2 = w_object2.as_methodcontext_get_shadow() assert w_object2.fetch(constants.CTXPART_SENDER_INDEX) == w_object assert s_object.w_self() == w_object @@ -112,7 +113,6 @@ w_object.store(idx, 'f') w_object.store(idx + 1, 'g') w_object.store(idx + 2, 'h') - s_object.update_shadow() assert s_object.stack() == ['f', 'g', 'h' ] assert s_object.top() == 'h' s_object.push('i') @@ -121,8 +121,6 @@ assert s_object.pop() == 'i' assert s_object.pop_and_return_n(2) == ['g', 'h'] assert s_object.pop() == 'f' - s_object.update_w_self() - s_object.update_shadow() assert s_object.stackpointer() == s_object.stackstart() def test_methodcontext(): From afa at codespeak.net Tue May 20 15:57:53 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 20 May 2008 15:57:53 +0200 (CEST) Subject: [pypy-svn] r54998 - pypy/branch/win32port/pypy/module/signal Message-ID: <20080520135753.3686F1684EC@codespeak.net> Author: afa Date: Tue May 20 15:57:51 2008 New Revision: 54998 Modified: pypy/branch/win32port/pypy/module/signal/interp_signal.py Log: Allow compilation of signal module on win32 Modified: pypy/branch/win32port/pypy/module/signal/interp_signal.py ============================================================================== --- pypy/branch/win32port/pypy/module/signal/interp_signal.py (original) +++ pypy/branch/win32port/pypy/module/signal/interp_signal.py Tue May 20 15:57:51 2008 @@ -21,7 +21,8 @@ eci = ExternalCompilationInfo( includes = ['stdlib.h', 'src/signals.h'], separate_module_sources = ['#include '], - include_dirs = [str(py.path.local(autopath.pypydir).join('translator', 'c'))] + include_dirs = [str(py.path.local(autopath.pypydir).join('translator', 'c'))], + export_symbols = ['pypysig_poll'], ) def external(name, args, result, **kwds): From cami at codespeak.net Tue May 20 16:03:16 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Tue, 20 May 2008 16:03:16 +0200 (CEST) Subject: [pypy-svn] r54999 - in pypy/dist/pypy/rlib/rsdl: . test Message-ID: <20080520140316.B528B1684F4@codespeak.net> Author: cami Date: Tue May 20 16:03:09 2008 New Revision: 54999 Modified: pypy/dist/pypy/rlib/rsdl/RSDL.py pypy/dist/pypy/rlib/rsdl/test/test_video.py Log: removed useless mousescrolloffset test changed initialization of RSDL for use with the translator and on the mac changed file path ro SDLMain.m to work with gcc Modified: pypy/dist/pypy/rlib/rsdl/RSDL.py ============================================================================== --- pypy/dist/pypy/rlib/rsdl/RSDL.py (original) +++ pypy/dist/pypy/rlib/rsdl/RSDL.py Tue May 20 16:03:09 2008 @@ -2,14 +2,23 @@ from pypy.rpython.tool import rffi_platform as platform from pypy.translator.tool.cbuild import ExternalCompilationInfo from pypy.rlib.rsdl.constants import _constants +from pypy.rlib.objectmodel import we_are_translated +import py import sys if sys.platform == 'darwin': eci = ExternalCompilationInfo( - includes = ['SDL.h'], - include_dirs = ['/Library/Frameworks/SDL.framework/Versions/A/Headers'], + includes = ['SDL.h', + #'Init.h', + #'SDLMain.m' + #'SDLMain.h'*/ + ], + include_dirs = ['/Library/Frameworks/SDL.framework/Versions/A/Headers', + #str(py.magic.autopath().dirpath().join('macosx-sdl-main')) + ], link_extra = [ - 'macosx-sdl-main/SDLMain.m', + str(py.magic.autopath().dirpath().join('macosx-sdl-main/SDLMain.m')), + #'macosx-sdl-main/SDLMain.m', '-I', '/Library/Frameworks/SDL.framework/Versions/A/Headers', ], frameworks = ['SDL', 'Cocoa'] @@ -119,19 +128,21 @@ Sint16P = lltype.Ptr(lltype.Array(Sint16, hints={'nolength': True})) Uint32P = lltype.Ptr(lltype.Array(Uint32, hints={'nolength': True})) -# ------------------------------------------------------------------------------ - -def Init(flags): - if sys.platform == 'darwin': - from AppKit import NSApplication - NSApplication.sharedApplication() - return _Init(flags) # ------------------------------------------------------------------------------ _Init = external('SDL_Init', [Uint32], rffi.INT) +#static void CustomApplicationMain (int argc, char **argv) + +CustomApplicationMain = external('CustomApplicationMain', + [rffi.INT, rffi.CCHARP], + lltype.Void) + +Mac_Init = external('SDL_Init', + [Uint32], + rffi.INT) Quit = external('SDL_Quit', [], lltype.Void) @@ -209,3 +220,20 @@ UpdateRect = external('SDL_UpdateRect', [SurfacePtr, rffi.INT, rffi.INT, rffi.INT], lltype.Void) + +# ------------------------------------------------------------------------------ + + +if sys.platform == 'darwin': + def Init(flags): + if not we_are_translated(): + from AppKit import NSApplication + NSApplication.sharedApplication() + #CustomApplicationMain(0, " ") + return _Init(flags) + #Mac_Init() +else: + Init = _Init + + + \ No newline at end of file Modified: pypy/dist/pypy/rlib/rsdl/test/test_video.py ============================================================================== --- pypy/dist/pypy/rlib/rsdl/test/test_video.py (original) +++ pypy/dist/pypy/rlib/rsdl/test/test_video.py Tue May 20 16:03:09 2008 @@ -151,44 +151,6 @@ py.test.fail("") finally: lltype.free(event, flavor='raw') - - def test_mousewheel(self): - if not self.is_interactive: - py.test.skip("interactive test only") - print - print "Press the given MouseButtons:" - print " Use Escape to quit." - - event_tests = [("scroll up", RSDL.BUTTON_WHEELUP), - ("scroll down", RSDL.BUTTON_WHEELDOWN)] - test_success = [] - event = lltype.malloc(RSDL.Event, flavor='raw') - try: - for button_test in event_tests: - print " press %s:" % button_test[0] - while True: - ok = RSDL.WaitEvent(event) - assert rffi.cast(lltype.Signed, ok) == 1 - c_type = rffi.getintfield(event, 'c_type') - if c_type == RSDL.MOUSEBUTTONDOWN: - b = rffi.cast(RSDL.MouseButtonEventPtr, event) - print "down", rffi.getintfield(b, "c_x"), \ - rffi.getintfield(b, "c_y") - elif c_type == RSDL.MOUSEBUTTONUP: - b = rffi.cast(RSDL.MouseButtonEventPtr, event) - print "up", rffi.getintfield(b, "c_x"), \ - rffi.getintfield(b, "c_y") - elif c_type == RSDL.KEYUP: - p = rffi.cast(RSDL.KeyboardEventPtr, event) - if rffi.getintfield(p.c_keysym, 'c_sym') == RSDL.K_ESCAPE: - test_success.append(False) - print " manually aborted" - break - #break - if False in test_success: - py.test.fail("") - finally: - lltype.free(event, flavor='raw') def test_show_hide_cursor(self): From afa at codespeak.net Tue May 20 16:04:24 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 20 May 2008 16:04:24 +0200 (CEST) Subject: [pypy-svn] r55000 - pypy/branch/win32port/pypy/lib Message-ID: <20080520140424.1C6B51684F4@codespeak.net> Author: afa Date: Tue May 20 16:04:20 2008 New Revision: 55000 Modified: pypy/branch/win32port/pypy/lib/_subprocess.py Log: Refactor _subprocess.py Modified: pypy/branch/win32port/pypy/lib/_subprocess.py ============================================================================== --- pypy/branch/win32port/pypy/lib/_subprocess.py (original) +++ pypy/branch/win32port/pypy/lib/_subprocess.py Tue May 20 16:04:20 2008 @@ -1,4 +1,85 @@ -import ctypes as _ctypes +""" +Support routines for subprocess module. +Currently, this extension module is only required when using the +subprocess module on Windows. +""" + + +# Declare external Win32 functions + +import ctypes + +_kernel32 = ctypes.WinDLL('kernel32') + +_CloseHandle = _kernel32.CloseHandle +_CloseHandle.argtypes = [ctypes.c_int] +_CloseHandle.restype = ctypes.c_int + +_CreatePipe = _kernel32.CreatePipe +_CreatePipe.argtypes = [ctypes.POINTER(ctypes.c_int), ctypes.POINTER(ctypes.c_int), + ctypes.c_void_p, ctypes.c_int] +_CreatePipe.restype = ctypes.c_int + +_GetCurrentProcess = _kernel32.GetCurrentProcess +_GetCurrentProcess.argtypes = [] +_GetCurrentProcess.restype = ctypes.c_int + +_DuplicateHandle = _kernel32.DuplicateHandle +_DuplicateHandle.argtypes = [ctypes.c_int, ctypes.c_int, ctypes.c_int, + ctypes.POINTER(ctypes.c_int), + ctypes.c_int, ctypes.c_int, ctypes.c_int] +_DuplicateHandle.restype = ctypes.c_int + +_WaitForSingleObject = _kernel32.WaitForSingleObject +_WaitForSingleObject.argtypes = [ctypes.c_int, ctypes.c_int] +_WaitForSingleObject.restype = ctypes.c_int + +_GetExitCodeProcess = _kernel32.GetExitCodeProcess +_GetExitCodeProcess.argtypes = [ctypes.c_int, ctypes.POINTER(ctypes.c_int)] +_GetExitCodeProcess.restype = ctypes.c_int + +_GetStdHandle = _kernel32.GetStdHandle +_GetStdHandle.argtypes = [ctypes.c_int] +_GetStdHandle.restype = ctypes.c_int + +class _STARTUPINFO(ctypes.Structure): + _fields_ = [('cb', ctypes.c_int), + ('lpReserved', ctypes.c_void_p), + ('lpDesktop', ctypes.c_char_p), + ('lpTitle', ctypes.c_char_p), + ('dwX', ctypes.c_int), + ('dwY', ctypes.c_int), + ('dwXSize', ctypes.c_int), + ('dwYSize', ctypes.c_int), + ('dwXCountChars', ctypes.c_int), + ('dwYCountChars', ctypes.c_int), + ("dwFillAttribute", ctypes.c_int), + ("dwFlags", ctypes.c_int), + ("wShowWindow", ctypes.c_short), + ("cbReserved2", ctypes.c_short), + ("lpReserved2", ctypes.c_void_p), + ("hStdInput", ctypes.c_int), + ("hStdOutput", ctypes.c_int), + ("hStdError", ctypes.c_int) + ] + +class _PROCESS_INFORMATION(ctypes.Structure): + _fields_ = [("hProcess", ctypes.c_int), + ("hThread", ctypes.c_int), + ("dwProcessID", ctypes.c_int), + ("dwThreadID", ctypes.c_int)] + +_CreateProcess = _kernel32.CreateProcessA +_CreateProcess.argtypes = [ctypes.c_char_p, ctypes.c_char_p, ctypes.c_void_p, ctypes.c_void_p, + ctypes.c_int, ctypes.c_int, ctypes.c_char_p, ctypes.c_char_p, + ctypes.POINTER(_STARTUPINFO), ctypes.POINTER(_PROCESS_INFORMATION)] +_CreateProcess.restype = ctypes.c_int + +del ctypes + +# Now the _subprocess module implementation + +from ctypes import c_int as _c_int, byref as _byref class _handle: def __init__(self, handle): @@ -12,24 +93,15 @@ return handle def Close(self): - _CloseHandle = _ctypes.WinDLL('kernel32').CloseHandle - _CloseHandle.argtypes = [_ctypes.c_int] - _CloseHandle.restype = _ctypes.c_int - if self.handle not in (-1, None): _CloseHandle(self.handle) self.handle = None def CreatePipe(attributes, size): - _CreatePipe = _ctypes.WinDLL('kernel32').CreatePipe - _CreatePipe.argtypes = [_ctypes.POINTER(_ctypes.c_int), _ctypes.POINTER(_ctypes.c_int), - _ctypes.c_void_p, _ctypes.c_int] - _CreatePipe.restype = _ctypes.c_int + read = _c_int() + write = _c_int() - read = _ctypes.c_int() - write = _ctypes.c_int() - - res = _CreatePipe(_ctypes.byref(read), _ctypes.byref(write), None, size) + res = _CreatePipe(_byref(read), _byref(write), None, size) if not res: raise WindowsError("Error") @@ -37,24 +109,14 @@ return _handle(read.value), _handle(write.value) def GetCurrentProcess(): - _GetCurrentProcess = _ctypes.WinDLL('kernel32').GetCurrentProcess - _GetCurrentProcess.argtypes = [] - _GetCurrentProcess.restype = _ctypes.c_int - return _handle(_GetCurrentProcess()) def DuplicateHandle(source_process, source, target_process, access, inherit, options=0): - _DuplicateHandle = _ctypes.WinDLL('kernel32').DuplicateHandle - _DuplicateHandle.argtypes = [_ctypes.c_int, _ctypes.c_int, _ctypes.c_int, - _ctypes.POINTER(_ctypes.c_int), - _ctypes.c_int, _ctypes.c_int, _ctypes.c_int] - _DuplicateHandle.restype = _ctypes.c_int - - target = _ctypes.c_int() + target = _c_int() res = _DuplicateHandle(int(source_process), int(source), int(target_process), - _ctypes.byref(target), + _byref(target), access, inherit, options) if not res: @@ -66,40 +128,7 @@ def CreateProcess(name, command_line, process_attr, thread_attr, inherit, flags, env, start_dir, startup_info): - _CreateProcess = _ctypes.WinDLL('kernel32').CreateProcessA - _CreateProcess.argtypes = [_ctypes.c_char_p, _ctypes.c_char_p, _ctypes.c_void_p, _ctypes.c_void_p, - _ctypes.c_int, _ctypes.c_int, _ctypes.c_char_p, _ctypes.c_char_p, - _ctypes.c_void_p, _ctypes.c_void_p] - _CreateProcess.restype = _ctypes.c_int - - class STARTUPINFO(_ctypes.Structure): - _fields_ = [('cb', _ctypes.c_int), - ('lpReserved', _ctypes.c_void_p), - ('lpDesktop', _ctypes.c_char_p), - ('lpTitle', _ctypes.c_char_p), - ('dwX', _ctypes.c_int), - ('dwY', _ctypes.c_int), - ('dwXSize', _ctypes.c_int), - ('dwYSize', _ctypes.c_int), - ('dwXCountChars', _ctypes.c_int), - ('dwYCountChars', _ctypes.c_int), - ("dwFillAttribute", _ctypes.c_int), - ("dwFlags", _ctypes.c_int), - ("wShowWindow", _ctypes.c_short), - ("cbReserved2", _ctypes.c_short), - ("lpReserved2", _ctypes.c_void_p), - ("hStdInput", _ctypes.c_int), - ("hStdOutput", _ctypes.c_int), - ("hStdError", _ctypes.c_int) - ] - - class PROCESS_INFORMATION(_ctypes.Structure): - _fields_ = [("hProcess", _ctypes.c_int), - ("hThread", _ctypes.c_int), - ("dwProcessID", _ctypes.c_int), - ("dwThreadID", _ctypes.c_int)] - - si = STARTUPINFO() + si = _STARTUPINFO() si.dwFlags = startup_info.dwFlags si.wShowWindow = getattr(startup_info, 'wShowWindow', 0) if startup_info.hStdInput: @@ -109,7 +138,7 @@ if startup_info.hStdError: si.hStdError = startup_info.hStdError.handle - pi = PROCESS_INFORMATION() + pi = _PROCESS_INFORMATION() if env is not None: envbuf = "" @@ -120,7 +149,7 @@ envbuf = None res = _CreateProcess(name, command_line, None, None, inherit, flags, envbuf, - start_dir, _ctypes.byref(si), _ctypes.byref(pi)) + start_dir, _byref(si), _byref(pi)) if not res: raise WindowsError("Error") @@ -129,10 +158,6 @@ STARTF_USESTDHANDLES = 0x100 def WaitForSingleObject(handle, milliseconds): - _WaitForSingleObject = _ctypes.WinDLL('kernel32').WaitForSingleObject - _WaitForSingleObject.argtypes = [_ctypes.c_int, _ctypes.c_int] - _WaitForSingleObject.restype = _ctypes.c_int - res = _WaitForSingleObject(handle.handle, milliseconds) if res < 0: @@ -143,13 +168,9 @@ WAIT_OBJECT_0 = 0 def GetExitCodeProcess(handle): - _GetExitCodeProcess = _ctypes.WinDLL('kernel32').GetExitCodeProcess - _GetExitCodeProcess.argtypes = [_ctypes.c_int, _ctypes.POINTER(_ctypes.c_int)] - _GetExitCodeProcess.restype = _ctypes.c_int - - code = _ctypes.c_int() + code = _c_int() - res = _GetExitCodeProcess(handle.handle, _ctypes.byref(code)) + res = _GetExitCodeProcess(handle.handle, _byref(code)) if not res: raise WindowsError("Error") @@ -157,10 +178,6 @@ return code.value def GetStdHandle(stdhandle): - _GetStdHandle = _ctypes.WinDLL('kernel32').GetStdHandle - _GetStdHandle.argtypes = [_ctypes.c_int] - _GetStdHandle.restype = _ctypes.c_int - res = _GetStdHandle(stdhandle) if not res: From cami at codespeak.net Tue May 20 16:11:12 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Tue, 20 May 2008 16:11:12 +0200 (CEST) Subject: [pypy-svn] r55001 - pypy/dist/pypy/rlib/rsdl Message-ID: <20080520141112.85DB8168069@codespeak.net> Author: cami Date: Tue May 20 16:11:07 2008 New Revision: 55001 Modified: pypy/dist/pypy/rlib/rsdl/RSDL.py Log: remove some useless externel test function bindingx Modified: pypy/dist/pypy/rlib/rsdl/RSDL.py ============================================================================== --- pypy/dist/pypy/rlib/rsdl/RSDL.py (original) +++ pypy/dist/pypy/rlib/rsdl/RSDL.py Tue May 20 16:11:07 2008 @@ -134,11 +134,6 @@ _Init = external('SDL_Init', [Uint32], rffi.INT) -#static void CustomApplicationMain (int argc, char **argv) - -CustomApplicationMain = external('CustomApplicationMain', - [rffi.INT, rffi.CCHARP], - lltype.Void) Mac_Init = external('SDL_Init', [Uint32], From arigo at codespeak.net Tue May 20 16:11:38 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 20 May 2008 16:11:38 +0200 (CEST) Subject: [pypy-svn] r55002 - in pypy/dist/pypy/rlib/rsdl: . test Message-ID: <20080520141138.D94F2168069@codespeak.net> Author: arigo Date: Tue May 20 16:11:36 2008 New Revision: 55002 Modified: pypy/dist/pypy/rlib/rsdl/RSDL.py pypy/dist/pypy/rlib/rsdl/RSDL_helper.py pypy/dist/pypy/rlib/rsdl/test/test_video.py Log: Poll and mallocrect(). Modified: pypy/dist/pypy/rlib/rsdl/RSDL.py ============================================================================== --- pypy/dist/pypy/rlib/rsdl/RSDL.py (original) +++ pypy/dist/pypy/rlib/rsdl/RSDL.py Tue May 20 16:11:36 2008 @@ -68,7 +68,12 @@ ('pixels', rffi.UCHARP)]) PixelFormat = platform.Struct('SDL_PixelFormat', - [('BytesPerPixel', rffi.INT)]) + [('BitsPerPixel', rffi.INT), + ('BytesPerPixel', rffi.INT), + ('Rmask', rffi.INT), + ('Gmask', rffi.INT), + ('Bmask', rffi.INT), + ('Amask', rffi.INT)]) Event = platform.Struct('SDL_Event', [('type', rffi.INT)]) @@ -158,6 +163,10 @@ [EventPtr], rffi.INT) +PollEvent = external('SDL_PollEvent', + [EventPtr], + rffi.INT) + Flip = external('SDL_Flip', [SurfacePtr], rffi.INT) Modified: pypy/dist/pypy/rlib/rsdl/RSDL_helper.py ============================================================================== --- pypy/dist/pypy/rlib/rsdl/RSDL_helper.py (original) +++ pypy/dist/pypy/rlib/rsdl/RSDL_helper.py Tue May 20 16:11:36 2008 @@ -93,4 +93,10 @@ else: raise ValueError("bad BytesPerPixel") - +def mallocrect(x, y, w, h): + p = lltype.malloc(RSDL.Rect, flavor='raw') + rffi.setintfield(p, 'c_x', x) + rffi.setintfield(p, 'c_y', y) + rffi.setintfield(p, 'c_w', w) + rffi.setintfield(p, 'c_h', h) + return p Modified: pypy/dist/pypy/rlib/rsdl/test/test_video.py ============================================================================== --- pypy/dist/pypy/rlib/rsdl/test/test_video.py (original) +++ pypy/dist/pypy/rlib/rsdl/test/test_video.py Tue May 20 16:11:36 2008 @@ -76,8 +76,35 @@ print '(event of type %d)' % c_type finally: lltype.free(event, flavor='raw') - - + + def test_poll(self): + if not self.is_interactive: + py.test.skip("interactive test only") + import time, sys + RSDL.EnableUNICODE(1) + print + print "Keys pressed in the Pygame window give a dot." + print " Use Escape or wait 3 seconds to quit." + timeout = time.time() + 3 + event = lltype.malloc(RSDL.Event, flavor='raw') + try: + while True: + # busy polling + ok = RSDL.PollEvent(event) + ok = rffi.cast(lltype.Signed, ok) + assert ok >= 0 + if ok > 0: + c_type = rffi.getintfield(event, 'c_type') + if c_type == RSDL.KEYDOWN: + sys.stderr.write('.') + timeout = time.time() + 3 + else: + if time.time() > timeout: + break + time.sleep(0.05) + finally: + lltype.free(event, flavor='raw') + def test_mousemove(self): if not self.is_interactive: py.test.skip("interactive test only") @@ -187,16 +214,12 @@ color = RSDL.MapRGB(fmt, 255, 0, 0) RSDL.FillRect(surface, lltype.nullptr(RSDL.Rect), color) - paintrect = lltype.malloc(RSDL.Rect, flavor='raw') - rffi.setintfield(paintrect, 'c_x', 75) - rffi.setintfield(paintrect, 'c_y', 0) - rffi.setintfield(paintrect, 'c_w', 150) - rffi.setintfield(paintrect, 'c_h', 50) - color = RSDL.MapRGB(fmt, 255, 128, 0) - RSDL.FillRect(surface, paintrect, color) - + paintrect = RSDL_helper.mallocrect(75, 0, 150, 50) dstrect = lltype.malloc(RSDL.Rect, flavor='raw') try: + color = RSDL.MapRGB(fmt, 255, 128, 0) + RSDL.FillRect(surface, paintrect, color) + rffi.setintfield(dstrect, 'c_x', 10) rffi.setintfield(dstrect, 'c_y', 10) rffi.setintfield(dstrect, 'c_w', 150) From tverwaes at codespeak.net Tue May 20 16:12:10 2008 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Tue, 20 May 2008 16:12:10 +0200 (CEST) Subject: [pypy-svn] r55003 - in pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk: . test Message-ID: <20080520141210.9C5EE16852A@codespeak.net> Author: tverwaes Date: Tue May 20 16:12:09 2008 New Revision: 55003 Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/primitives.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_shadow.py Log: (cfbolz, tverwaes) moving factory methods for contexts from model to shadow Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py Tue May 20 16:12:09 2008 @@ -442,9 +442,9 @@ return w_literal.as_string() # XXX performance issue here def create_frame(self, receiver, arguments, sender = None): - from pypy.lang.smalltalk import objtable + from pypy.lang.smalltalk import objtable, shadow assert len(arguments) == self.argsize - w_new = W_MethodContext(self, receiver, arguments, sender) + w_new = shadow.MethodContextShadow.make_context(self, receiver, arguments, sender) return w_new def __str__(self): @@ -557,45 +557,6 @@ self.bytes = (self.bytes[:index0] + character + self.bytes[index0 + 1:]) -def W_BlockContext(w_home, w_sender, argcnt, initialip): - from pypy.lang.smalltalk.classtable import w_BlockContext - from pypy.lang.smalltalk import shadow - # create and attach a shadow manually, to not have to carefully put things - # into the right places in the W_PointersObject - # XXX could hack some more to never have to create the _vars of w_result - w_result = W_PointersObject(w_BlockContext, w_home.size()) - s_result = shadow.BlockContextShadow(w_result) - w_result._shadow = s_result - s_result.store_expected_argument_count(argcnt) - s_result.store_initialip(initialip) - s_result.store_w_home(w_home) - s_result.store_pc(initialip) - return w_result - -def W_MethodContext(w_method, w_receiver, - arguments, w_sender=None): - from pypy.lang.smalltalk.classtable import w_MethodContext - from pypy.lang.smalltalk import objtable, shadow - # From blue book: normal mc have place for 12 temps+maxstack - # mc for methods with islarge flag turned on 32 - size = 12 + w_method.islarge * 20 + w_method.argsize - w_result = w_MethodContext.as_class_get_shadow().new(size) - assert isinstance(w_result, W_PointersObject) - # create and attach a shadow manually, to not have to carefully put things - # into the right places in the W_PointersObject - # XXX could hack some more to never have to create the _vars of w_result - s_result = shadow.MethodContextShadow(w_result) - w_result._shadow = s_result - s_result.store_w_method(w_method) - if w_sender: - s_result.store_w_sender(w_sender) - s_result.store_w_receiver(w_receiver) - s_result.store_pc(0) - s_result._temps = [objtable.w_nil] * w_method.tempframesize() - for i in range(len(arguments)): - s_result.settemp(i, arguments[i]) - return w_result - # Use black magic to create w_nil without running the constructor, # thus allowing it to be used even in the constructor of its own # class. Note that we patch its class in objtable. Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/primitives.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/primitives.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/primitives.py Tue May 20 16:12:09 2008 @@ -637,7 +637,7 @@ # The block bytecodes are stored inline: so we skip past the # byteodes to invoke this primitive to find them (hence +2) initialip = frame.pc() + 2 - w_new_context = model.W_BlockContext( + w_new_context = shadow.BlockContextShadow.make_context( w_method_context, objtable.w_nil, argcnt, initialip) return w_new_context Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py Tue May 20 16:12:09 2008 @@ -479,8 +479,20 @@ class BlockContextShadow(ContextPartShadow): - def __init__(self, w_self): - ContextPartShadow.__init__(self, w_self) + @staticmethod + def make_context(w_home, w_sender, argcnt, initialip): + from pypy.lang.smalltalk.classtable import w_BlockContext + # create and attach a shadow manually, to not have to carefully put things + # into the right places in the W_PointersObject + # XXX could hack some more to never have to create the _vars of w_result + w_result = model.W_PointersObject(w_BlockContext, w_home.size()) + s_result = BlockContextShadow(w_result) + w_result._shadow = s_result + s_result.store_expected_argument_count(argcnt) + s_result.store_initialip(initialip) + s_result.store_w_home(w_home) + s_result.store_pc(initialip) + return w_result def fetch(self, n0): if n0 == constants.BLKCTX_HOME_INDEX: @@ -558,6 +570,31 @@ self._w_receiver = None ContextPartShadow.__init__(self, w_self) + @staticmethod + def make_context(w_method, w_receiver, + arguments, w_sender=None): + from pypy.lang.smalltalk.classtable import w_MethodContext + from pypy.lang.smalltalk import objtable + # From blue book: normal mc have place for 12 temps+maxstack + # mc for methods with islarge flag turned on 32 + size = 12 + w_method.islarge * 20 + w_method.argsize + w_result = w_MethodContext.as_class_get_shadow().new(size) + assert isinstance(w_result, model.W_PointersObject) + # create and attach a shadow manually, to not have to carefully put things + # into the right places in the W_PointersObject + # XXX could hack some more to never have to create the _vars of w_result + s_result = MethodContextShadow(w_result) + w_result._shadow = s_result + s_result.store_w_method(w_method) + if w_sender: + s_result.store_w_sender(w_sender) + s_result.store_w_receiver(w_receiver) + s_result.store_pc(0) + s_result._temps = [objtable.w_nil] * w_method.tempframesize() + for i in range(len(arguments)): + s_result.settemp(i, arguments[i]) + return w_result + def fetch(self, n0): if n0 == constants.MTHDCTX_METHOD: return self.w_method() Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_shadow.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_shadow.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_shadow.py Tue May 20 16:12:09 2008 @@ -135,36 +135,4 @@ assert s_object.getbytecode() == 101 assert s_object.s_home() == s_object -#def test_scheduler(): -# w_process = process() -# w_pl = model.W_PointersObject(None, 0) -# w_object = model.W_PointersObject(None, 2) -# w_object.store(constants.SCHEDULER_ACTIVE_PROCESS_INDEX, w_process) -# w_object.store(constants.SCHEDULER_PROCESS_LISTS_INDEX, w_pl) -# s_object = w_object.as_scheduler_get_shadow() -# assert s_object.s_active_process() == w_process.as_process_get_shadow() -# assert s_object.process_lists() == w_pl -# w_process2 = process() -# s_object.store_w_active_process(w_process2) -# assert s_object.process_lists() == w_pl -# assert s_object.s_active_process() != w_process.as_process_get_shadow() -# assert s_object.s_active_process() == w_process2.as_process_get_shadow() -#def test_shadowchanges(): -# w_object = model.W_PointersObject(None, 2) -# w_o1 = link('a') -# w_o2 = link('b') -# w_object.store(0, w_o1) -# w_object.store(1, w_o2) -# s_object = w_object.as_linkedlist_get_shadow() -# assert s_object.w_firstlink() == w_o1 -# assert s_object.w_lastlink() == w_o2 -# assert w_object._shadow == s_object -# s_object2 = w_object.as_association_get_shadow() -# assert s_object2.key() == w_o1 -# assert s_object2.value() == w_o2 -# assert w_object._shadow == s_object2 -# s_object.sync_shadow() -# assert s_object.w_firstlink() == w_o1 -# assert s_object.w_lastlink() == w_o2 -# assert w_object._shadow == s_object From cami at codespeak.net Tue May 20 16:13:09 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Tue, 20 May 2008 16:13:09 +0200 (CEST) Subject: [pypy-svn] r55004 - pypy/dist/pypy/translator/goal Message-ID: <20080520141309.A36B916853A@codespeak.net> Author: cami Date: Tue May 20 16:13:07 2008 New Revision: 55004 Added: pypy/dist/pypy/translator/goal/targetgbimplementation.py Modified: pypy/dist/pypy/translator/goal/targetgbrom4.py pypy/dist/pypy/translator/goal/targetsimplevideo.py Log: removed start imports added targetgbimplementation for "real" usage with roms targetsimplevideo: escaped some non working stuff, fixing now Added: pypy/dist/pypy/translator/goal/targetgbimplementation.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/goal/targetgbimplementation.py Tue May 20 16:13:07 2008 @@ -0,0 +1,41 @@ +import os +import py +from pypy.lang.gameboy.gameboyImplementation import GameBoyImplementation + + +ROM_PATH = str(py.magic.autopath().dirpath().dirpath().dirpath())+"/lang/gameboy/rom" +EMULATION_CYCLES = 64 + + +# This loads the whole mini.image in advance. At run-time, +# it executes the tinyBenchmark. In this way we get an RPython +# "image" frozen into the executable, mmap'ed by the OS from +# there and loaded lazily when needed :-) + + +# XXX this only compiles if sys.recursionlimit is high enough! +# On non-Linux platforms I don't know if there is enough stack to +# compile... +#sys.setrecursionlimit(100000) + + +def entry_point(argv=None): + if len(argv) > 1: + filename = argv[1] + else: + filename = ROM_PATH+"/rom9/rom9.gb" + gameBoy = GameBoyImplementation() + #gameBoy.load_cartridge_file(ROM_PATH+"/rom4/rom4.gb")#filename) + gameBoy.emulate(EMULATION_CYCLES) +# #gameBoy.load_cartridge_file(str(filename)) + + return 0 + + +# _____ Define and setup target ___ + +def target(*args): + return entry_point, None + +def test_target(): + entry_point(["boe", ROM_PATH+"/rom4/rom4.gb"]) Modified: pypy/dist/pypy/translator/goal/targetgbrom4.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetgbrom4.py (original) +++ pypy/dist/pypy/translator/goal/targetgbrom4.py Tue May 20 16:13:07 2008 @@ -1,9 +1,7 @@ import os import py from pypy.lang.gameboy import constants -from pypy.lang.gameboy.cpu import * -from pypy.lang.gameboy.cartridge import * -from pypy.lang.gameboy.gameboy import * +from pypy.lang.gameboy.gameboy import GameBoy ROM_PATH = str(py.magic.autopath().dirpath().dirpath().dirpath())+"/lang/gameboy/rom" @@ -26,11 +24,13 @@ if len(argv) > 1: filename = argv[1] else: - filename = ROM_PATH+"/rom4/rom4.gb" + filename = ROM_PATH+"/rom9/rom9.gb" gameBoy = GameBoy() #gameBoy.load_cartridge_file(ROM_PATH+"/rom4/rom4.gb")#filename) gameBoy.load_cartridge_file(str(filename)) - return gameBoy.emulate(EMULATION_CYCLES) + gameBoy.emulate(EMULATION_CYCLES) + + return 0 # _____ Define and setup target ___ Modified: pypy/dist/pypy/translator/goal/targetsimplevideo.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetsimplevideo.py (original) +++ pypy/dist/pypy/translator/goal/targetsimplevideo.py Tue May 20 16:13:07 2008 @@ -2,8 +2,8 @@ from pypy.rpython.lltypesystem import rffi, lltype import py -WIDTH = 200 -HEIGHT = 200 +WIDTH = 20 +HEIGHT = 20 def entry_point(argv=None): RSDL.Init(RSDL.INIT_VIDEO) >= 0 @@ -81,6 +81,7 @@ pattern[paintpattern % pl](screen, black, white) RSDL.UnlockSurface(screen) RSDL.Flip(screen) + RSDL.Delay(1000) # ----------------------------------------------------------------------------- @@ -88,6 +89,8 @@ def target(*args): return entry_point, None +def test_target(): + entry_point() if __name__ == '__main__': entry_point() From afa at codespeak.net Tue May 20 16:17:29 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 20 May 2008 16:17:29 +0200 (CEST) Subject: [pypy-svn] r55005 - in pypy/branch/win32port/pypy: lib lib/_ctypes module/_rawffi module/_rawffi/test rlib rlib/test Message-ID: <20080520141729.3216716853A@codespeak.net> Author: afa Date: Tue May 20 16:17:22 2008 New Revision: 55005 Modified: pypy/branch/win32port/pypy/lib/_ctypes/builtin.py pypy/branch/win32port/pypy/lib/msvcrt.py pypy/branch/win32port/pypy/module/_rawffi/__init__.py pypy/branch/win32port/pypy/module/_rawffi/interp_rawffi.py pypy/branch/win32port/pypy/module/_rawffi/test/test__rawffi.py pypy/branch/win32port/pypy/rlib/libffi.py pypy/branch/win32port/pypy/rlib/rwin32.py pypy/branch/win32port/pypy/rlib/test/test_libffi.py Log: Maciej was right: it's better to dynamically get the name of the msvcrt library: the same generated sources may be recompiled, e.g. in debug mode. I hope I got it right: in pypy-c.exe, we compile a function that retrieves the dll containing the "fopen" pointer address. Hardcoded "libc.so.6" on posix platforms. There must be a better way. Modified: pypy/branch/win32port/pypy/lib/_ctypes/builtin.py ============================================================================== --- pypy/branch/win32port/pypy/lib/_ctypes/builtin.py (original) +++ pypy/branch/win32port/pypy/lib/_ctypes/builtin.py Tue May 20 16:17:22 2008 @@ -5,8 +5,8 @@ encoding = 'ascii' errors = 'strict' -_memmove_addr = ('memmove', _rawffi.libc_name) -_memset_addr = ('memset', _rawffi.libc_name) +_memmove_addr = _rawffi.get_libc().getaddressindll('memmove') +_memset_addr = _rawffi.get_libc().getaddressindll('memset') def _string_at_addr(addr, lgt): # address here can be almost anything Modified: pypy/branch/win32port/pypy/lib/msvcrt.py ============================================================================== --- pypy/branch/win32port/pypy/lib/msvcrt.py (original) +++ pypy/branch/win32port/pypy/lib/msvcrt.py Tue May 20 16:17:22 2008 @@ -1,7 +1,15 @@ +""" +Python interface to the Microsoft Visual C Runtime +Library, providing access to those non-portable, but +still useful routines. +""" + +# XXX incomplete: implemented only functions needed by subprocess.py + import _rawffi import ctypes -_c = ctypes.CDLL(_rawffi.libc_name) +_c = ctypes.CDLL('msvcrt', _rawffi.get_libc()) open_osfhandle = _c._open_osfhandle open_osfhandle.argtypes = [ctypes.c_int, ctypes.c_int] @@ -9,6 +17,6 @@ get_osfhandle = _c._get_osfhandle get_osfhandle.argtypes = [ctypes.c_int] -open_osfhandle.restype = ctypes.c_int +get_osfhandle.restype = ctypes.c_int del ctypes Modified: pypy/branch/win32port/pypy/module/_rawffi/__init__.py ============================================================================== --- pypy/branch/win32port/pypy/module/_rawffi/__init__.py (original) +++ pypy/branch/win32port/pypy/module/_rawffi/__init__.py Tue May 20 16:17:22 2008 @@ -25,6 +25,7 @@ 'charp2rawstring' : 'interp_rawffi.charp2rawstring', 'CallbackPtr' : 'callback.W_CallbackPtr', '_num_of_allocated_objects' : 'tracker.num_of_allocated_objects', + 'get_libc' : 'interp_rawffi.get_libc', } appleveldefs = { @@ -44,10 +45,6 @@ ]: if hasattr(libffi, name): Module.interpleveldefs[name] = "space.wrap(%r)" % getattr(libffi, name) - - # Name of C runtime library - from pypy.rpython.lltypesystem.ll2ctypes import get_libc_name - Module.interpleveldefs['libc_name'] = "space.wrap(%r)" % get_libc_name() super(Module, cls).buildloaders() buildloaders = classmethod(buildloaders) Modified: pypy/branch/win32port/pypy/module/_rawffi/interp_rawffi.py ============================================================================== --- pypy/branch/win32port/pypy/module/_rawffi/interp_rawffi.py (original) +++ pypy/branch/win32port/pypy/module/_rawffi/interp_rawffi.py Tue May 20 16:17:22 2008 @@ -468,3 +468,9 @@ raise OperationError(space.w_WindowsError, space.wrap(hresult)) return space.wrap(hresult) check_HRESULT.unwrap_spec = [ObjSpace, int] + +def get_libc(space): + try: + return space.wrap(W_CDLL(space, get_libc_name())) + except OSError, e: + raise wrap_oserror(space, e) Modified: pypy/branch/win32port/pypy/module/_rawffi/test/test__rawffi.py ============================================================================== --- pypy/branch/win32port/pypy/module/_rawffi/test/test__rawffi.py (original) +++ pypy/branch/win32port/pypy/module/_rawffi/test/test__rawffi.py Tue May 20 16:17:22 2008 @@ -180,9 +180,13 @@ import _rawffi _rawffi.CDLL(self.libc_name) + def test_libc_load(self): + import _rawffi + _rawffi.get_libc() + def test_getattr(self): import _rawffi - libc = _rawffi.CDLL(self.libc_name) + libc = _rawffi.get_libc() func = libc.ptr('rand', [], 'i') assert libc.ptr('rand', [], 'i') is func # caching assert libc.ptr('rand', [], 'l') is not func @@ -292,7 +296,7 @@ def test_time(self): import _rawffi - libc = _rawffi.CDLL(self.libc_name) + libc = _rawffi.get_libc() time = libc.ptr('time', ['z'], 'l') # 'z' instead of 'P' just for test arg = _rawffi.Array('P')(1) arg[0] = 0 @@ -306,7 +310,7 @@ import _rawffi struct_type = _rawffi.Structure([('tv_sec', 'l'), ('tv_usec', 'l')]) structure = struct_type() - libc = _rawffi.CDLL(self.libc_name) + libc = _rawffi.get_libc() gettimeofday = libc.ptr('gettimeofday', ['P', 'P'], 'i') arg1 = structure.byptr() @@ -341,7 +345,7 @@ ("tm_wday", 'i'), ("tm_yday", 'i'), ("tm_isdst", 'i')]) - libc = _rawffi.CDLL(self.libc_name) + libc = _rawffi.get_libc() gmtime = libc.ptr('gmtime', ['P'], 'P') arg = x.byptr() @@ -452,7 +456,7 @@ skip("FIXME: compare actually receives a pair of int**") import _rawffi import struct - libc = _rawffi.CDLL(self.libc_name) + libc = _rawffi.get_libc() ll_to_sort = _rawffi.Array('i')(4) for i in range(4): ll_to_sort[i] = 4-i Modified: pypy/branch/win32port/pypy/rlib/libffi.py ============================================================================== --- pypy/branch/win32port/pypy/rlib/libffi.py (original) +++ pypy/branch/win32port/pypy/rlib/libffi.py Tue May 20 16:17:22 2008 @@ -37,15 +37,31 @@ else: libffidir = py.path.local(pypydir).join('translator', 'c', 'src', 'libffi_msvc') eci = ExternalCompilationInfo( + pre_include_lines = ['#define _WIN32_WINNT 0x501'], includes = ['ffi.h', 'windows.h'], libraries = ['kernel32'], include_dirs = [libffidir], + separate_module_sources = [''' + #include + + /* Get the module where the "fopen" function resides in */ + HANDLE get_libc_handle() { + MEMORY_BASIC_INFORMATION mi; + memset(&mi, 0, sizeof(mi)); + + if( !VirtualQueryEx(GetCurrentProcess(), &fopen, &mi, sizeof(mi)) ) + return 0; + + return (HMODULE)mi.AllocationBase; + } + '''], separate_module_files = [libffidir.join('ffi.c'), libffidir.join('prep_cif.c'), libffidir.join('win32.c'), libffidir.join('pypy_ffi.c'), ], - export_symbols = ['ffi_call', 'ffi_prep_cif', 'ffi_prep_closure'], + export_symbols = ['ffi_call', 'ffi_prep_cif', 'ffi_prep_closure', + 'get_libc_handle'], ) FFI_TYPE_P = lltype.Ptr(lltype.ForwardReference()) @@ -193,6 +209,9 @@ # XXX rffi.cast here... return res + def get_libc_name(): + return 'libc.so.6' + if _MS_WINDOWS: def dlopen(name): res = rwin32.LoadLibrary(name) @@ -218,6 +237,12 @@ FormatError = rwin32.FormatError LoadLibrary = rwin32.LoadLibrary + get_libc_handle = external('get_libc_handle', [], rwin32.HANDLE) + + def get_libc_name(): + return rwin32.GetModuleFileName(get_libc_handle()) + + FFI_OK = cConfig.FFI_OK FFI_BAD_TYPEDEF = cConfig.FFI_BAD_TYPEDEF FFI_DEFAULT_ABI = rffi.cast(rffi.USHORT, cConfig.FFI_DEFAULT_ABI) @@ -518,3 +543,4 @@ def getaddressindll(self, name): return dlsym(self.lib, name) + Modified: pypy/branch/win32port/pypy/rlib/rwin32.py ============================================================================== --- pypy/branch/win32port/pypy/rlib/rwin32.py (original) +++ pypy/branch/win32port/pypy/rlib/rwin32.py Tue May 20 16:17:22 2008 @@ -56,6 +56,7 @@ if WIN32: HANDLE = rffi.ULONG LPHANDLE = rffi.CArrayPtr(HANDLE) + HMODULE = HANDLE GetLastError = winexternal('GetLastError', [], DWORD) @@ -95,4 +96,16 @@ def FAILED(hr): return rffi.cast(HRESULT, hr) < 0 - + + _GetModuleFileName = winexternal('GetModuleFileNameA', + [HMODULE, rffi.CCHARP, DWORD], + DWORD) + + def GetModuleFileName(module): + size = 255 # MAX_PATH + buf = lltype.malloc(rffi.CCHARP.TO, size, flavor='raw') + res = _GetModuleFileName(module, buf, size) + if not res: + return '' + else: + return ''.join([buf[i] for i in range(res)]) Modified: pypy/branch/win32port/pypy/rlib/test/test_libffi.py ============================================================================== --- pypy/branch/win32port/pypy/rlib/test/test_libffi.py (original) +++ pypy/branch/win32port/pypy/rlib/test/test_libffi.py Tue May 20 16:17:22 2008 @@ -360,3 +360,11 @@ del lib assert not ALLOCATED + +class TestWin32Handles: + def test_get_libc_handle(self): + handle = get_libc_handle() + print get_libc_name() + print hex(handle) + assert handle != 0 + assert handle % 0x1000 == 0 From tverwaes at codespeak.net Tue May 20 16:20:01 2008 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Tue, 20 May 2008 16:20:01 +0200 (CEST) Subject: [pypy-svn] r55006 - pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk Message-ID: <20080520142001.2EA9116853C@codespeak.net> Author: tverwaes Date: Tue May 20 16:19:59 2008 New Revision: 55006 Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py Log: (cfbolz, tverwaes): use official interface to set shadow. Add an attach_shadow to caching Shadows and put the update_shadow call there. clear instance variables when a redirecting shadow is attached. Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py Tue May 20 16:19:59 2008 @@ -21,16 +21,15 @@ def sync_shadow(self): pass class AbstractCachingShadow(AbstractShadow): - def __init__(self, w_self): - AbstractShadow.__init__(self, w_self) - self.update_shadow() - def invalidate_shadow(self): """This should get called whenever the base Smalltalk object changes.""" if not self.invalid: self.invalid = True + def attach_shadow(self): + self.update_shadow() + def sync_shadow(self): if self.invalid: self.update_shadow() @@ -282,6 +281,7 @@ AbstractShadow.attach_shadow(self) for i in range(self._w_self_size): self.copy_from_w_self(i) + self.w_self()._vars = None def detach_shadow(self): self.w_self()._vars = [objtable.w_nil] * self._w_self_size @@ -487,7 +487,7 @@ # XXX could hack some more to never have to create the _vars of w_result w_result = model.W_PointersObject(w_BlockContext, w_home.size()) s_result = BlockContextShadow(w_result) - w_result._shadow = s_result + w_result.store_shadow(s_result) s_result.store_expected_argument_count(argcnt) s_result.store_initialip(initialip) s_result.store_w_home(w_home) @@ -517,7 +517,7 @@ def attach_shadow(self): # Make sure the home context is updated first self.copy_from_w_self(constants.BLKCTX_HOME_INDEX) - ContextPartShadow.update_shadow(self) + ContextPartShadow.attach_shadow(self) def store_unwrap_initialip(self, w_value): initialip = utility.unwrap_int(w_value) @@ -584,7 +584,7 @@ # into the right places in the W_PointersObject # XXX could hack some more to never have to create the _vars of w_result s_result = MethodContextShadow(w_result) - w_result._shadow = s_result + w_result.store_shadow(s_result) s_result.store_w_method(w_method) if w_sender: s_result.store_w_sender(w_sender) From arigo at codespeak.net Tue May 20 16:26:49 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 20 May 2008 16:26:49 +0200 (CEST) Subject: [pypy-svn] r55007 - pypy/dist/pypy/config Message-ID: <20080520142649.333E016853A@codespeak.net> Author: arigo Date: Tue May 20 16:26:45 2008 New Revision: 55007 Modified: pypy/dist/pypy/config/pypyoption.py Log: Try to enable this by default. Modified: pypy/dist/pypy/config/pypyoption.py ============================================================================== --- pypy/dist/pypy/config/pypyoption.py (original) +++ pypy/dist/pypy/config/pypyoption.py Tue May 20 16:26:45 2008 @@ -326,6 +326,7 @@ ("objspace.std.optimized_list_getitem", True), ("objspace.std.getattributeshortcut", True), ("translation.list_comprehension_operations",True), + ("translation.backendopt.remove_asserts",True), ], cmdline="--allopts --faassen", negation=False), From tverwaes at codespeak.net Tue May 20 16:34:25 2008 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Tue, 20 May 2008 16:34:25 +0200 (CEST) Subject: [pypy-svn] r55008 - pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk Message-ID: <20080520143425.B0AAA16853F@codespeak.net> Author: tverwaes Date: Tue May 20 16:34:16 2008 New Revision: 55008 Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/wrapper.py Log: (cfbolz, tverwaes) go over usages of _vars and replace by nicer usage if necessary. Also fix size() for shadowed pointersobjects Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py Tue May 20 16:34:16 2008 @@ -254,6 +254,11 @@ return self.varsize() def size(self): + if self._shadow is not None: + return self._shadow.size() + return self._size() + + def _size(self): return len(self._vars) def invariant(self): Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py Tue May 20 16:34:16 2008 @@ -12,6 +12,8 @@ return self.w_self()._fetch(n0) def store(self, n0, w_value): return self.w_self()._store(n0, w_value) + def size(self): + return self.w_self()._size() def w_self(self): return self._w_self def getname(self): @@ -81,7 +83,7 @@ w_self = self.w_self() # read and painfully decode the format classformat = utility.unwrap_int( - w_self._vars[constants.CLASS_FORMAT_INDEX]) + w_self._fetch(constants.CLASS_FORMAT_INDEX)) # The classformat in Squeak, as an integer value, is: # <2 bits=instSize//64><5 bits=cClass><4 bits=instSpec> # <6 bits=instSize\\64><1 bit=0> @@ -118,10 +120,10 @@ self.guess_class_name() # read the methoddict - self.w_methoddict = w_self._vars[constants.CLASS_METHODDICT_INDEX] + self.w_methoddict = w_self._fetch(constants.CLASS_METHODDICT_INDEX) assert isinstance(self.w_methoddict, model.W_PointersObject) - w_superclass = w_self._vars[constants.CLASS_SUPERCLASS_INDEX] + w_superclass = w_self._fetch(constants.CLASS_SUPERCLASS_INDEX) if w_superclass.is_same_object(w_nil): self.w_superclass = None else: @@ -133,7 +135,7 @@ # read the name if w_self.size() > constants.CLASS_NAME_INDEX: - w_name = w_self._vars[constants.CLASS_NAME_INDEX] + w_name = w_self._fetch(constants.CLASS_NAME_INDEX) else: # Some heuristic to find the classname # Only used for debugging @@ -142,10 +144,10 @@ # we are probably holding a metaclass instead of a class. # metaclasses hold a pointer to the real class in the last # slot. This is pos 6 in mini.image and higher in squeak3.9 - w_realclass = w_self._vars[w_self.size() - 1] + w_realclass = w_self._fetch(w_self.size() - 1) assert isinstance(w_realclass, model.W_PointersObject) if w_realclass.size() > constants.CLASS_NAME_INDEX: - w_name = w_realclass._vars[constants.CLASS_NAME_INDEX] + w_name = w_realclass.__fetch(onstants.CLASS_NAME_INDEX) if isinstance(w_name, model.W_BytesObject): self.name = w_name.as_string() @@ -230,7 +232,7 @@ "NOT_RPYTHON" # this is only for testing. if self.w_methoddict is None: self.w_methoddict = model.W_PointersObject(None, 2) - self.w_methoddict._vars[1] = model.W_PointersObject(None, 0) + self.w_methoddict._store(1, model.W_PointersObject(None, 0)) self.s_methoddict().invalid = False def installmethod(self, selector, method): @@ -248,7 +250,7 @@ def sync_cache(self): from pypy.lang.smalltalk import objtable - w_values = self.w_self()._vars[constants.METHODDICT_VALUES_INDEX] + w_values = self.w_self()._fetch(constants.METHODDICT_VALUES_INDEX) assert isinstance(w_values, model.W_PointersObject) s_values = w_values.get_shadow() # XXX Should add! @@ -256,12 +258,12 @@ size = self.w_self().size() - constants.METHODDICT_NAMES_INDEX self.methoddict = {} for i in range(size): - w_selector = self.w_self()._vars[constants.METHODDICT_NAMES_INDEX+i] + w_selector = self.w_self()._fetch(constants.METHODDICT_NAMES_INDEX+i) if not w_selector.is_same_object(objtable.w_nil): if not isinstance(w_selector, model.W_BytesObject): raise ClassShadowError("bogus selector in method dict") selector = w_selector.as_string() - w_compiledmethod = w_values._vars[i] + w_compiledmethod = w_values._fetch(i) if not isinstance(w_compiledmethod, model.W_CompiledMethod): raise ClassShadowError("the methoddict must contain " "CompiledMethods only for now") @@ -271,11 +273,13 @@ class AbstractRedirectingShadow(AbstractShadow): def __init__(self, w_self): AbstractShadow.__init__(self, w_self) - self._w_self_size = len(self.w_self()._vars) + self._w_self_size = self.w_self().size() def fetch(self, n0): raise NotImplementedError() def store(self, n0, w_value): raise NotImplementedError() + def size(self): + return self._w_self_size def attach_shadow(self): AbstractShadow.attach_shadow(self) Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/wrapper.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/wrapper.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/wrapper.py Tue May 20 16:34:16 2008 @@ -10,13 +10,13 @@ def read(self, index0): try: - return self.w_self._vars[index0] + return self.w_self.fetch(index0) except IndexError: raise WrapperException("Unexpected instance layout. Too small") def write(self, index0, w_new): try: - self.w_self._vars[index0] = w_new + self.w_self.store(index0, w_new) except IndexError: raise WrapperException("Unexpected instance layout. Too small") @@ -154,7 +154,7 @@ # Asserts as W_PointersObject lists = Wrapper(w_lists) - for i in range(len(w_lists._vars) -1, -1, -1): + for i in range(w_lists.size() - 1, -1, -1): process_list = ProcessListWrapper(lists.read(i)) if not process_list.is_empty_list(): return process_list.remove_first_link_of_list() From cami at codespeak.net Tue May 20 16:38:22 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Tue, 20 May 2008 16:38:22 +0200 (CEST) Subject: [pypy-svn] r55009 - pypy/dist/pypy/translator/goal Message-ID: <20080520143822.A94BE16853F@codespeak.net> Author: cami Date: Tue May 20 16:38:17 2008 New Revision: 55009 Modified: pypy/dist/pypy/translator/goal/targetgbrom4.py Log: remove old squeakimage comment Modified: pypy/dist/pypy/translator/goal/targetgbrom4.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetgbrom4.py (original) +++ pypy/dist/pypy/translator/goal/targetgbrom4.py Tue May 20 16:38:17 2008 @@ -8,25 +8,12 @@ EMULATION_CYCLES = 64 -# This loads the whole mini.image in advance. At run-time, -# it executes the tinyBenchmark. In this way we get an RPython -# "image" frozen into the executable, mmap'ed by the OS from -# there and loaded lazily when needed :-) - - -# XXX this only compiles if sys.recursionlimit is high enough! -# On non-Linux platforms I don't know if there is enough stack to -# compile... -#sys.setrecursionlimit(100000) - - def entry_point(argv=None): if len(argv) > 1: filename = argv[1] else: filename = ROM_PATH+"/rom9/rom9.gb" gameBoy = GameBoy() - #gameBoy.load_cartridge_file(ROM_PATH+"/rom4/rom4.gb")#filename) gameBoy.load_cartridge_file(str(filename)) gameBoy.emulate(EMULATION_CYCLES) From fijal at codespeak.net Tue May 20 16:48:37 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 20 May 2008 16:48:37 +0200 (CEST) Subject: [pypy-svn] r55010 - in pypy/branch/hybrid-io/pypy: rlib rpython rpython/lltypesystem rpython/ootypesystem Message-ID: <20080520144837.394FE16853F@codespeak.net> Author: fijal Date: Tue May 20 16:48:35 2008 New Revision: 55010 Modified: pypy/branch/hybrid-io/pypy/rlib/rstring.py pypy/branch/hybrid-io/pypy/rpython/lltypesystem/rbuilder.py pypy/branch/hybrid-io/pypy/rpython/ootypesystem/rbuilder.py pypy/branch/hybrid-io/pypy/rpython/rbuilder.py Log: (arigo, fijal) Remove the constant requirement for initial size of string builder Modified: pypy/branch/hybrid-io/pypy/rlib/rstring.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rlib/rstring.py (original) +++ pypy/branch/hybrid-io/pypy/rlib/rstring.py Tue May 20 16:48:35 2008 @@ -3,7 +3,10 @@ """ from pypy.rpython.extregistry import ExtRegistryEntry -from pypy.rpython.annlowlevel import llhelper +from pypy.annotation.model import SomeObject, SomeString, s_None,\ + SomeChar, SomeInteger, SomeUnicodeCodePoint, SomeUnicodeString + +# -------------- public API --------------------------------- INIT_SIZE = 100 # XXX tweak @@ -28,17 +31,67 @@ def build(self): return u''.join(self.l) +# ------------------------------------------------------------ +# ----------------- implementation details ------------------- +# ------------------------------------------------------------ + +class SomeStringBuilder(SomeObject): + def method_append(self, s_str): + assert isinstance(s_str, (SomeString, SomeChar)) + return s_None + + def method_append_slice(self, s_str, s_start, s_end): + assert isinstance(s_str, SomeString) + assert isinstance(s_start, SomeInteger) + assert isinstance(s_end, SomeInteger) + assert s_start.nonneg + assert s_end.nonneg + return s_None + + def method_append_multiple_char(self, s_char, s_times): + assert isinstance(s_char, SomeChar) + assert isinstance(s_times, SomeInteger) + assert s_times.nonneg + return s_None + + def method_build(self): + return SomeString() + + def rtyper_makerepr(self, rtyper): + return rtyper.type_system.rbuilder.stringbuilder_repr + +class SomeUnicodeBuilder(SomeObject): + def method_append(self, s_str): + assert isinstance(s_str, (SomeUnicodeCodePoint, SomeUnicodeString)) + return s_None + + def method_append_slice(self, s_str, s_start, s_end): + assert isinstance(s_str, SomeUnicodeString) + assert isinstance(s_start, SomeInteger) + assert isinstance(s_end, SomeInteger) + assert s_start.nonneg + assert s_end.nonneg + return s_None + + def method_append_multiple_char(self, s_char, s_times): + assert isinstance(s_char, SomeUnicodeCodePoint) + assert isinstance(s_times, SomeInteger) + assert s_times.nonneg + return s_None + + def method_build(self): + return SomeUnicodeString() + + def rtyper_makerepr(self, rtyper): + return rtyper.type_system.rbuilder.unicodebuilder_repr + class BaseEntry(object): def compute_result_annotation(self, s_init_size=None): - from pypy.rpython.rbuilder import SomeStringBuilder, SomeUnicodeBuilder if s_init_size is not None: - assert s_init_size.is_constant() - init_size = s_init_size.const - else: - init_size = INIT_SIZE + assert isinstance(s_init_size, SomeInteger) if self.use_unicode: - return SomeUnicodeBuilder(init_size) - return SomeStringBuilder(init_size) + return SomeUnicodeBuilder() + return SomeStringBuilder() def specialize_call(self, hop): return hop.r_result.rtyper_new(hop) Modified: pypy/branch/hybrid-io/pypy/rpython/lltypesystem/rbuilder.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/lltypesystem/rbuilder.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/lltypesystem/rbuilder.py Tue May 20 16:48:35 2008 @@ -1,7 +1,8 @@ from pypy.rpython.rbuilder import AbstractStringBuilderRepr from pypy.rpython.lltypesystem import lltype -from pypy.rpython.lltypesystem.rstr import STR, UNICODE +from pypy.rpython.lltypesystem.rstr import STR, UNICODE, char_repr,\ + string_repr, unichar_repr, unicode_repr from pypy.rpython.annlowlevel import llstr from pypy.rlib import rgc from pypy.rpython.lltypesystem.lltype import staticAdtMethod @@ -85,10 +86,14 @@ class StringBuilderRepr(BaseStringBuilderRepr): lowleveltype = lltype.Ptr(STRINGBUILDER) basetp = STR + string_repr = string_repr + char_repr = char_repr class UnicodeBuilderRepr(BaseStringBuilderRepr): lowleveltype = lltype.Ptr(UNICODEBUILDER) basetp = UNICODE + string_repr = unicode_repr + char_repr = unichar_repr unicodebuilder_repr = UnicodeBuilderRepr() stringbuilder_repr = StringBuilderRepr() Modified: pypy/branch/hybrid-io/pypy/rpython/ootypesystem/rbuilder.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/ootypesystem/rbuilder.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/ootypesystem/rbuilder.py Tue May 20 16:48:35 2008 @@ -1,6 +1,8 @@ from pypy.rpython.rbuilder import AbstractStringBuilderRepr from pypy.rpython.ootypesystem import ootype +from pypy.rpython.ootypesystem.rstr import string_repr, char_repr,\ + unicode_repr, unichar_repr class BaseBuilderRepr(AbstractStringBuilderRepr): @classmethod @@ -32,9 +34,13 @@ class StringBuilderRepr(BaseBuilderRepr): lowleveltype = ootype.StringBuilder + string_repr = string_repr + char_repr = char_repr class UnicodeBuilderRepr(BaseBuilderRepr): lowleveltype = ootype.UnicodeBuilder + string_repr = unicode_repr + char_repr = unichar_repr stringbuilder_repr = StringBuilderRepr() unicodebuilder_repr = UnicodeBuilderRepr() Modified: pypy/branch/hybrid-io/pypy/rpython/rbuilder.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/rbuilder.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/rbuilder.py Tue May 20 16:48:35 2008 @@ -1,90 +1,43 @@ -from pypy.annotation.model import SomeObject, SomeString, s_None,\ - SomeChar, SomeInteger, SomeUnicodeCodePoint, SomeUnicodeString from pypy.rpython.rmodel import Repr from pypy.rpython.annlowlevel import llhelper from pypy.rpython.lltypesystem import lltype - -class SomeStringBuilder(SomeObject): - def __init__(self, init_size): - self.init_size = init_size - - def method_append(self, s_str): - assert isinstance(s_str, (SomeString, SomeChar)) - return s_None - - def method_append_slice(self, s_str, s_start, s_end): - assert isinstance(s_str, SomeString) - assert isinstance(s_start, SomeInteger) - assert isinstance(s_end, SomeInteger) - assert s_start.nonneg - assert s_end.nonneg - return s_None - - def method_append_multiple_char(self, s_char, s_times): - assert isinstance(s_char, SomeChar) - assert isinstance(s_times, SomeInteger) - assert s_times.nonneg - return s_None - - def method_build(self): - return SomeString() - - def rtyper_makerepr(self, rtyper): - return rtyper.type_system.rbuilder.stringbuilder_repr - -class SomeUnicodeBuilder(SomeObject): - def __init__(self, init_size): - self.init_size = init_size - - def method_append(self, s_str): - assert isinstance(s_str, (SomeUnicodeCodePoint, SomeUnicodeString)) - return s_None - - def method_append_slice(self, s_str, s_start, s_end): - assert isinstance(s_str, SomeUnicodeString) - assert isinstance(s_start, SomeInteger) - assert isinstance(s_end, SomeInteger) - assert s_start.nonneg - assert s_end.nonneg - return s_None - - def method_append_multiple_char(self, s_char, s_times): - assert isinstance(s_char, SomeUnicodeCodePoint) - assert isinstance(s_times, SomeInteger) - assert s_times.nonneg - return s_None - - def method_build(self): - return SomeUnicodeString() - - def rtyper_makerepr(self, rtyper): - return rtyper.type_system.rbuilder.unicodebuilder_repr +from pypy.rlib.rstring import INIT_SIZE +from pypy.annotation.model import SomeChar, SomeUnicodeCodePoint class AbstractStringBuilderRepr(Repr): def rtyper_new(self, hop): repr = hop.r_result if len(hop.args_v) == 0: - v_arg = hop.inputconst(lltype.Signed, hop.s_result.init_size) + v_arg = hop.inputconst(lltype.Signed, INIT_SIZE) else: v_arg = hop.inputarg(lltype.Signed, 0) + hop.exception_cannot_occur() return hop.gendirectcall(self.ll_new, v_arg) def rtype_method_append(self, hop): - vlist = hop.inputargs(*hop.args_r) if isinstance(hop.args_s[1], (SomeChar, SomeUnicodeCodePoint)): - return hop.gendirectcall(self.ll_append_char, *vlist) - return hop.gendirectcall(self.ll_append, *vlist) + vlist = hop.inputargs(self, self.char_repr) + func = self.ll_append_char + else: + vlist = hop.inputargs(self, self.string_repr) + func = self.ll_append + hop.exception_cannot_occur() + return hop.gendirectcall(func, *vlist) def rtype_method_append_slice(self, hop): - vlist = hop.inputargs(*hop.args_r) + vlist = hop.inputargs(self, self.string_repr, + lltype.Signed, lltype.Signed) + hop.exception_cannot_occur() return hop.gendirectcall(self.ll_append_slice, *vlist) def rtype_method_append_multiple_char(self, hop): - vlist = hop.inputargs(*hop.args_r) + vlist = hop.inputargs(self, self.char_repr, lltype.Signed) + hop.exception_cannot_occur() return hop.gendirectcall(self.ll_append_multiple_char, *vlist) def rtype_method_build(self, hop): - vlist = hop.inputargs(*hop.args_r) + vlist = hop.inputargs(self) + hop.exception_cannot_occur() return hop.gendirectcall(self.ll_build, *vlist) From hpk at codespeak.net Tue May 20 16:49:25 2008 From: hpk at codespeak.net (hpk at codespeak.net) Date: Tue, 20 May 2008 16:49:25 +0200 (CEST) Subject: [pypy-svn] r55011 - pypy/django/tests Message-ID: <20080520144925.4308F16853F@codespeak.net> Author: hpk Date: Tue May 20 16:49:24 2008 New Revision: 55011 Modified: pypy/django/tests/conftest.py Log: find plain docstrings in test modules, try to improve support for "invalid model test cases" Modified: pypy/django/tests/conftest.py ============================================================================== --- pypy/django/tests/conftest.py (original) +++ pypy/django/tests/conftest.py Tue May 20 16:49:24 2008 @@ -1,14 +1,21 @@ import py import os +import sys -# XXX ignores invalid models path +# XXX after invalid model tests the testing process bails out! # XXX no django/contrib rootdir = py.path.local(__file__).dirpath() pkgroot = rootdir.dirpath() -if str(pkgroot) not in py.std.sys.path: - py.std.sys.path.append(str(pkgroot)) +if str(pkgroot) not in sys.path: + sys.path.append(str(pkgroot)) + +# allows us to import from runtests +if str(rootdir) not in sys.path: + sys.path.append(str(rootdir)) +from runtests import InvalidModelTestCase + DIRNAMES = ['modeltests', 'regressiontests']#, 'django/contrib'] @@ -63,7 +70,10 @@ def _tests_from_mod(self, mod): result = [] - if hasattr(mod, 'suite'): + # "invalid" test case + if self.name.startswith("invalid"): + return ["%invalidtestcase%"] + elif hasattr(mod, 'suite'): s = mod.suite() namemethods = getmethods2(s) meth = [] @@ -85,6 +95,8 @@ def _find_doctests(self, mod): if hasattr(mod, '__test__') and mod.__test__.get('API_TESTS'): return ['%docstring%'] + if os.path.basename(mod.__file__).startswith("tests") and mod.__doc__: + return ['%docmodulestring%'] #return [)] return [] @@ -110,11 +122,22 @@ elif name == 'tests.%docstring%': mod = mod.tests return DocTestItem(self.fspath.basename + '.%docstring%', mod, mod.__test__['API_TESTS']) + elif name == '%docmodulestring%': + return DocTestItem(self.fspath.basename + '.%docstring%', mod, mod.__doc__) + elif name == 'tests.%docmodulestring%': + return DocTestItem(self.fspath.basename + '.test.%docstring%', mod, mod.__doc__) + elif name == '%invalidtestcase%': + return DjangoInvalidModelTestCase(name, self) elif name.startswith('tests'): return DjangoUnitTest(name, self) else: return DjangoUnitTest(name, self) +class DjangoInvalidModelTestCase(py.test.collect.Item): + def run(self): + testcase = InvalidModelTestCase(self.parent.name) + run_testcase_method(testcase) + class DjangoUnitTest(py.test.collect.Item): def run(self): names = self.name.split(".") @@ -151,7 +174,7 @@ models = [] for model in self.fspath.listdir(): f = str(model.basename) - if f.startswith('__init__') or f.startswith('.') or f.startswith('sql') or f.startswith('invalid'): + if f.startswith('__init__') or f.startswith('.') or f.startswith('sql'): # or f.startswith("invalid"): pass else: models.append(f) @@ -216,8 +239,6 @@ Directory = DjangoTestDirectory Module = DjangoTestModule -# the below taken from pypy/lib-python/conftest.py - def getmethodnames(cls): l = [] for name, obj in vars(cls).items(): @@ -241,8 +262,6 @@ raise TypeError, "expected TestSuite or TestClass, got %r" %(suite_or_class) return res - - def run_testcase_method(method): result = method.defaultTestResult() method.run(result) From arigo at codespeak.net Tue May 20 17:02:18 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 20 May 2008 17:02:18 +0200 (CEST) Subject: [pypy-svn] r55012 - pypy/dist/pypy/rlib/rsdl/test Message-ID: <20080520150218.DBC35168548@codespeak.net> Author: arigo Date: Tue May 20 17:02:17 2008 New Revision: 55012 Modified: pypy/dist/pypy/rlib/rsdl/test/test_video.py Log: Fix test to match what it says. Modified: pypy/dist/pypy/rlib/rsdl/test/test_video.py ============================================================================== --- pypy/dist/pypy/rlib/rsdl/test/test_video.py (original) +++ pypy/dist/pypy/rlib/rsdl/test/test_video.py Tue May 20 17:02:17 2008 @@ -97,6 +97,10 @@ c_type = rffi.getintfield(event, 'c_type') if c_type == RSDL.KEYDOWN: sys.stderr.write('.') + p = rffi.cast(RSDL.KeyboardEventPtr, event) + if rffi.getintfield(p.c_keysym, 'c_sym') == RSDL.K_ESCAPE: + print 'Escape key' + break timeout = time.time() + 3 else: if time.time() > timeout: From fijal at codespeak.net Tue May 20 17:04:47 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 20 May 2008 17:04:47 +0200 (CEST) Subject: [pypy-svn] r55013 - in pypy/branch/hybrid-io/pypy/rpython: lltypesystem ootypesystem Message-ID: <20080520150447.8A8E516854C@codespeak.net> Author: fijal Date: Tue May 20 17:04:46 2008 New Revision: 55013 Modified: pypy/branch/hybrid-io/pypy/rpython/lltypesystem/rbuilder.py pypy/branch/hybrid-io/pypy/rpython/ootypesystem/rbuilder.py Log: (arigo, fijal) Be a bit paranoid about size estimates. Modified: pypy/branch/hybrid-io/pypy/rpython/lltypesystem/rbuilder.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/lltypesystem/rbuilder.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/lltypesystem/rbuilder.py Tue May 20 17:04:46 2008 @@ -32,9 +32,13 @@ ('buf', lltype.Ptr(UNICODE)), adtmeths={'grow':staticAdtMethod(unicodebuilder_grow)}) +MAX = 16*1024*1024 + class BaseStringBuilderRepr(AbstractStringBuilderRepr): @classmethod def ll_new(cls, init_size): + if init_size < 0 or init_size > MAX: + init_size = MAX ll_builder = lltype.malloc(cls.lowleveltype.TO) ll_builder.allocated = init_size ll_builder.used = 0 Modified: pypy/branch/hybrid-io/pypy/rpython/ootypesystem/rbuilder.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/ootypesystem/rbuilder.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/ootypesystem/rbuilder.py Tue May 20 17:04:46 2008 @@ -4,9 +4,13 @@ from pypy.rpython.ootypesystem.rstr import string_repr, char_repr,\ unicode_repr, unichar_repr +MAX = 16*1024*1024 + class BaseBuilderRepr(AbstractStringBuilderRepr): @classmethod def ll_new(cls, init_size): + if init_size < 0 or init_size > MAX: + init_size = MAX return ootype.new(cls.lowleveltype) @staticmethod From cami at codespeak.net Tue May 20 17:07:45 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Tue, 20 May 2008 17:07:45 +0200 (CEST) Subject: [pypy-svn] r55014 - in pypy/dist/pypy/rlib/rsdl: . test Message-ID: <20080520150745.56588168557@codespeak.net> Author: cami Date: Tue May 20 17:07:43 2008 New Revision: 55014 Modified: pypy/dist/pypy/rlib/rsdl/RSDL.py pypy/dist/pypy/rlib/rsdl/test/test_basic.py pypy/dist/pypy/rlib/rsdl/test/test_video.py Log: remove misleading comment in test_video added GetKeyName to resolve a KeySym Modified: pypy/dist/pypy/rlib/rsdl/RSDL.py ============================================================================== --- pypy/dist/pypy/rlib/rsdl/RSDL.py (original) +++ pypy/dist/pypy/rlib/rsdl/RSDL.py Tue May 20 17:07:43 2008 @@ -43,6 +43,7 @@ KeyboardEventPtr = lltype.Ptr(lltype.ForwardReference()) MouseButtonEventPtr = lltype.Ptr(lltype.ForwardReference()) MouseMotionEventPtr = lltype.Ptr(lltype.ForwardReference()) +KeyPtr = lltype.Ptr(lltype.ForwardReference()) # ------------------------------------------------------------------------------ @@ -225,6 +226,10 @@ [SurfacePtr, rffi.INT, rffi.INT, rffi.INT], lltype.Void) +GetKeyName = external('SDL_GetKeyName', + [rffi.INT], + rffi.CCHARP) + # ------------------------------------------------------------------------------ Modified: pypy/dist/pypy/rlib/rsdl/test/test_basic.py ============================================================================== --- pypy/dist/pypy/rlib/rsdl/test/test_basic.py (original) +++ pypy/dist/pypy/rlib/rsdl/test/test_basic.py Tue May 20 17:07:43 2008 @@ -20,3 +20,11 @@ assert rffi.getintfield(surface, 'c_h') == 50 RSDL.FreeSurface(surface) RSDL.Quit() + + +def test_get_keyname(): + assert RSDL.Init(RSDL.INIT_VIDEO) >= 0 + assert RSDL.GetKeyName(RSDL.K_PLUS)[0] == '+' + assert RSDL.GetKeyName(RSDL.K_RIGHTPAREN)[0] == ')' + assert RSDL.GetKeyName(RSDL.K_z)[0] == 'z' + Modified: pypy/dist/pypy/rlib/rsdl/test/test_video.py ============================================================================== --- pypy/dist/pypy/rlib/rsdl/test/test_video.py (original) +++ pypy/dist/pypy/rlib/rsdl/test/test_video.py Tue May 20 17:07:43 2008 @@ -84,7 +84,7 @@ RSDL.EnableUNICODE(1) print print "Keys pressed in the Pygame window give a dot." - print " Use Escape or wait 3 seconds to quit." + print " Wait 3 seconds to quit." timeout = time.time() + 3 event = lltype.malloc(RSDL.Event, flavor='raw') try: @@ -148,7 +148,7 @@ py.test.skip("interactive test only") print print "Press the given MouseButtons:" - print " Use Escape to quit." + print " Use Escape to pass tests." event_tests = [("left button", RSDL.BUTTON_LEFT), ("middle button", RSDL.BUTTON_MIDDLE), From hpk at codespeak.net Tue May 20 17:20:45 2008 From: hpk at codespeak.net (hpk at codespeak.net) Date: Tue, 20 May 2008 17:20:45 +0200 (CEST) Subject: [pypy-svn] r55015 - pypy/django/tests Message-ID: <20080520152045.1F60F168524@codespeak.net> Author: hpk Date: Tue May 20 17:20:45 2008 New Revision: 55015 Modified: pypy/django/tests/conftest.py Log: (anto, hpk with samuele around) trying to run invalid model tests with a teardown so that it doesn't break django Modified: pypy/django/tests/conftest.py ============================================================================== --- pypy/django/tests/conftest.py (original) +++ pypy/django/tests/conftest.py Tue May 20 17:20:45 2008 @@ -57,6 +57,8 @@ class DjangoTestModule(py.test.collect.Module): def run(self): + if self.name.startswith("invalid"): + return ["%invalidtestcase%"] mod = self._get_mod() result = self._tests_from_mod(mod) modpath = py.path.local(mod.__file__) @@ -71,9 +73,7 @@ def _tests_from_mod(self, mod): result = [] # "invalid" test case - if self.name.startswith("invalid"): - return ["%invalidtestcase%"] - elif hasattr(mod, 'suite'): + if hasattr(mod, 'suite'): s = mod.suite() namemethods = getmethods2(s) meth = [] @@ -116,6 +116,8 @@ return mod def join(self, name): + if name == '%invalidtestcase%': + return DjangoInvalidModelTestCase(name, self) mod = self._get_mod() if name == '%docstring%': return DocTestItem(self.fspath.basename + '.%docstring%', mod, mod.__test__['API_TESTS']) @@ -126,8 +128,6 @@ return DocTestItem(self.fspath.basename + '.%docstring%', mod, mod.__doc__) elif name == 'tests.%docmodulestring%': return DocTestItem(self.fspath.basename + '.test.%docstring%', mod, mod.__doc__) - elif name == '%invalidtestcase%': - return DjangoInvalidModelTestCase(name, self) elif name.startswith('tests'): return DjangoUnitTest(name, self) else: @@ -135,8 +135,14 @@ class DjangoInvalidModelTestCase(py.test.collect.Item): def run(self): + return testcase = InvalidModelTestCase(self.parent.name) - run_testcase_method(testcase) + try: + run_testcase_method(testcase) + finally: + from django.conf import settings + basedir = self.fspath.dirpath().basename + settings.INSTALLED_APPS.remove(basedir + "." + self.parent.name) class DjangoUnitTest(py.test.collect.Item): def run(self): From cami at codespeak.net Tue May 20 17:25:52 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Tue, 20 May 2008 17:25:52 +0200 (CEST) Subject: [pypy-svn] r55016 - pypy/dist/pypy/translator/goal Message-ID: <20080520152552.4C1A516853C@codespeak.net> Author: cami Date: Tue May 20 17:25:50 2008 New Revision: 55016 Modified: pypy/dist/pypy/translator/goal/targetgbimplementation.py Log: remove old squeakminiinagetest text in the header fixed joypaddriver translates now correctly Modified: pypy/dist/pypy/translator/goal/targetgbimplementation.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetgbimplementation.py (original) +++ pypy/dist/pypy/translator/goal/targetgbimplementation.py Tue May 20 17:25:50 2008 @@ -7,28 +7,15 @@ EMULATION_CYCLES = 64 -# This loads the whole mini.image in advance. At run-time, -# it executes the tinyBenchmark. In this way we get an RPython -# "image" frozen into the executable, mmap'ed by the OS from -# there and loaded lazily when needed :-) - - -# XXX this only compiles if sys.recursionlimit is high enough! -# On non-Linux platforms I don't know if there is enough stack to -# compile... -#sys.setrecursionlimit(100000) - - def entry_point(argv=None): if len(argv) > 1: filename = argv[1] else: filename = ROM_PATH+"/rom9/rom9.gb" + print "using file: ", str(filename) gameBoy = GameBoyImplementation() - #gameBoy.load_cartridge_file(ROM_PATH+"/rom4/rom4.gb")#filename) + gameBoy.load_cartridge_file(ROM_PATH+"/rom4/rom4.gb") gameBoy.emulate(EMULATION_CYCLES) -# #gameBoy.load_cartridge_file(str(filename)) - return 0 From tverwaes at codespeak.net Tue May 20 17:36:47 2008 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Tue, 20 May 2008 17:36:47 +0200 (CEST) Subject: [pypy-svn] r55017 - in pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk: . test Message-ID: <20080520153647.CBD0D1684F4@codespeak.net> Author: tverwaes Date: Tue May 20 17:36:45 2008 New Revision: 55017 Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_shadow.py Log: (cfbolz, tverwaes) making sure that detaching redirecting shadows fix their pointersobject correctly Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py Tue May 20 17:36:45 2008 @@ -124,6 +124,13 @@ return False return self.value == other.value + def __eq__(self, other): + return self.value == other.value + + def __ne__(self, other): + return not self == other + + class W_Float(W_Object): """Boxed float value.""" def __init__(self, value): @@ -149,6 +156,12 @@ # TODO is that correct in Squeak? return self.value == other.value + def __eq__(self, other): + return self.value == other.value + + def __ne__(self, other): + return not self == other + class W_AbstractObjectWithIdentityHash(W_Object): """Object with explicit hash (ie all except small ints and floats).""" @@ -265,8 +278,6 @@ return (W_AbstractObjectWithClassReference.invariant(self) and isinstance(self._vars, list)) - # XXX XXX - # Find better way of overloading shadows... def store_shadow(self, shadow): self._shadow = shadow Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py Tue May 20 17:36:45 2008 @@ -288,10 +288,10 @@ self.w_self()._vars = None def detach_shadow(self): + from pypy.lang.smalltalk import objtable self.w_self()._vars = [objtable.w_nil] * self._w_self_size for i in range(self._w_self_size): self.copy_to_w_self(i) - self.invalidate_shadow() def copy_from_w_self(self, n0): self.store(n0, self.w_self()._fetch(n0)) @@ -316,9 +316,9 @@ return self.wrap_pc() if n0 == constants.CTXPART_STACKP_INDEX: return self.wrap_stackpointer() - if self.stackstart() <= n0 < self.stackpointer(): + if self.stackstart() <= n0 < self.external_stackpointer(): return self._stack[n0-self.stackstart()] - if self.stackpointer() <= n0 < self.stackend(): + if self.external_stackpointer() <= n0 < self.stackend(): from pypy.lang.smalltalk import objtable return objtable.w_nil else: @@ -333,10 +333,10 @@ return self.store_unwrap_pc(w_value) if n0 == constants.CTXPART_STACKP_INDEX: return self.unwrap_store_stackpointer(w_value) - if self.stackstart() <= n0 < self.stackpointer(): + if self.stackstart() <= n0 < self.external_stackpointer(): self._stack[n0 - self.stackstart()] = w_value return - if self.stackpointer() <= n0 < self.stackend(): + if self.external_stackpointer() <= n0 < self.stackend(): return else: # XXX later should store tail out of known context part as well @@ -359,11 +359,12 @@ self._stack.extend(add) def wrap_stackpointer(self): - return utility.wrap_int(self.stackpointer() + 1) + return utility.wrap_int(len(self._stack) + + self.w_method().tempframesize()) # TODO test - def stackpointer(self): - return self.stackstart() + len(self._stack) + def external_stackpointer(self): + return len(self._stack) + self.stackstart() def w_home(self): raise NotImplementedError() Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_shadow.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_shadow.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_shadow.py Tue May 20 17:36:45 2008 @@ -121,7 +121,7 @@ assert s_object.pop() == 'i' assert s_object.pop_and_return_n(2) == ['g', 'h'] assert s_object.pop() == 'f' - assert s_object.stackpointer() == s_object.stackstart() + assert s_object.external_stackpointer() == s_object.stackstart() def test_methodcontext(): w_m = method() @@ -135,4 +135,12 @@ assert s_object.getbytecode() == 101 assert s_object.s_home() == s_object - +def test_swap_shadows(): + w_m = method() + w_object = methodcontext(pc=13, method=w_m) + old_vars = w_object._vars + s_object = w_object.as_methodcontext_get_shadow() + assert w_object._vars is None + s_object.detach_shadow() + assert w_object._vars == old_vars + assert w_object._vars is not old_vars From exarkun at codespeak.net Tue May 20 17:36:58 2008 From: exarkun at codespeak.net (exarkun at codespeak.net) Date: Tue, 20 May 2008 17:36:58 +0200 (CEST) Subject: [pypy-svn] r55018 - pypy/build/bot Message-ID: <20080520153658.A33111684FB@codespeak.net> Author: exarkun Date: Tue May 20 17:36:57 2008 New Revision: 55018 Modified: pypy/build/bot/pypybuilders.py Log: use baseURL instead of svnurl; building on branches works now also, disable twisted tests, since building on branches _does not_ ever work if you have two svn steps in one build. Modified: pypy/build/bot/pypybuilders.py ============================================================================== --- pypy/build/bot/pypybuilders.py (original) +++ pypy/build/bot/pypybuilders.py Tue May 20 17:36:57 2008 @@ -108,7 +108,8 @@ self.addStep( SVN, workdir="build/pypy-src", - svnurl="http://codespeak.net/svn/pypy/dist", + baseURL="http://codespeak.net/svn/pypy/", + defaultBranch="dist", mode="copy") self.addStep(PySwitch) @@ -151,25 +152,25 @@ testArguments=["-A"] + list(arg for arg in pytestArguments if arg != "--boxed"), timeout=60 * 60) - self.addStep(FileUpload, - slavesrc="pypy-src/pypy/translator/goal/pypy-c", - masterdest="pypy-c") - - self.addStep( - SVN, - workdir="build/Twisted-src", - svnurl="svn://svn.twistedmatrix.com/svn/Twisted/trunk", - mode="copy") - - self.addStep( - Trial, - workdir="build/pypy-src/pypy/translator/goal", - python=["pypy-c", - "--oldstyle"], - testpath=None, - trial="../../../../Twisted-src/bin/trial", - tests=["twisted"], - env={"PATH": "."}) +# self.addStep(FileUpload, +# slavesrc="pypy-src/pypy/translator/goal/pypy-c", +# masterdest="pypy-c") +# +# self.addStep( +# SVN, +# workdir="build/Twisted-src", +# svnurl="svn://svn.twistedmatrix.com/svn/Twisted/trunk", +# mode="copy") +# +# self.addStep( +# Trial, +# workdir="build/pypy-src/pypy/translator/goal", +# python=["pypy-c", +# "--oldstyle"], +# testpath=None, +# trial="../../../../Twisted-src/bin/trial", +# tests=["twisted"], +# env={"PATH": "."}) From cami at codespeak.net Tue May 20 17:39:55 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Tue, 20 May 2008 17:39:55 +0200 (CEST) Subject: [pypy-svn] r55019 - pypy/dist/pypy/translator/goal Message-ID: <20080520153955.A73FD1684F4@codespeak.net> Author: cami Date: Tue May 20 17:39:54 2008 New Revision: 55019 Modified: pypy/dist/pypy/translator/goal/targetsimplevideo.py Log: reduced the refresh delay to make the test usable Modified: pypy/dist/pypy/translator/goal/targetsimplevideo.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetsimplevideo.py (original) +++ pypy/dist/pypy/translator/goal/targetsimplevideo.py Tue May 20 17:39:54 2008 @@ -81,7 +81,7 @@ pattern[paintpattern % pl](screen, black, white) RSDL.UnlockSurface(screen) RSDL.Flip(screen) - RSDL.Delay(1000) + RSDL.Delay(10 ) # ----------------------------------------------------------------------------- From cami at codespeak.net Tue May 20 17:45:28 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Tue, 20 May 2008 17:45:28 +0200 (CEST) Subject: [pypy-svn] r55020 - pypy/dist/pypy/lang/gameboy Message-ID: <20080520154528.E6AAE168045@codespeak.net> Author: cami Date: Tue May 20 17:45:25 2008 New Revision: 55020 Modified: pypy/dist/pypy/lang/gameboy/cartridge.py pypy/dist/pypy/lang/gameboy/cpu.py pypy/dist/pypy/lang/gameboy/gameboyImplementation.py Log: some bugfixes made gameboyImplementation workable gameboyImplementation with keyboard feedback working Modified: pypy/dist/pypy/lang/gameboy/cartridge.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/cartridge.py (original) +++ pypy/dist/pypy/lang/gameboy/cartridge.py Tue May 20 17:45:25 2008 @@ -194,14 +194,12 @@ def create_battery_file_path(self, cartridge_file_path): if cartridge_file_path.endswith(constants.CARTRIDGE_FILE_EXTENSION): - return cartridge_file_path.replace( - constants.CARTRIDGE_FILE_EXTENSION, - constants.BATTERY_FILE_EXTENSION) + return cartridge_file_path[-len(constants.CARTRIDGE_FILE_EXTENSION)] \ + +constants.BATTERY_FILE_EXTENSION elif cartridge_file_path.endswith( constants.CARTRIDGE_COLOR_FILE_EXTENSION): - return cartridge_file_path.replace( - constants.CARTRIDGE_COLOR_FILE_EXTENSION, - constants.BATTERY_FILE_EXTENSION) + return cartridge_file_path[-len(constants.CARTRIDGE_COLOR_FILE_EXTENSION)] \ + +constants.BATTERY_FILE_EXTENSION else: return cartridge_file_path + constants.BATTERY_FILE_EXTENSION Modified: pypy/dist/pypy/lang/gameboy/cpu.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/cpu.py (original) +++ pypy/dist/pypy/lang/gameboy/cpu.py Tue May 20 17:45:25 2008 @@ -198,7 +198,7 @@ self.halted = False self.cycles = 0 self.ini_registers() - self.rom = [] + self.rom = [0] self.reset() def ini_registers(self): Modified: pypy/dist/pypy/lang/gameboy/gameboyImplementation.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/gameboyImplementation.py (original) +++ pypy/dist/pypy/lang/gameboy/gameboyImplementation.py Tue May 20 17:45:25 2008 @@ -5,7 +5,10 @@ from pypy.lang.gameboy.joypad import JoypadDriver from pypy.lang.gameboy.video import VideoDriver from pypy.lang.gameboy.sound import SoundDriver +from pypy.lang.gameboy.timer import Clock from pypy.rlib.rsdl import RSDL, RSDL_helper +from pypy.rpython.lltypesystem import lltype, rffi +from pypy.rlib.objectmodel import specialize # GAMEBOY ---------------------------------------------------------------------- @@ -15,33 +18,46 @@ def __init__(self): GameBoy.__init__(self) self.init_sdl() - #self.mainLoop() + self.mainLoop() def init_sdl(self): assert RSDL.Init(RSDL.INIT_VIDEO) >= 0 self.event = lltype.malloc(RSDL.Event, flavor='raw') - def create_window(self): - self.win = None - #self.win = window.Window() - #self.win.set_caption("PyBoy a GameBoy (TM)") - pass - def create_drivers(self): self.clock = Clock() self.joypad_driver = JoypadDriverImplementation() self.video_driver = VideoDriverImplementation() self.sound_driver = SoundDriverImplementation() - + + def mainLoop(self): try: - while not self.win.has_exit: - self.joypad_driver.update( self.event) - self.emulate(5) - time.sleep(0.01) + while True: + if self.poll_event(): + if self.check_for_escape(): + break + self.joypad_driver.update(self.event) + #self.emulate(5) + #time.sleep(0.01) finally: - lltype.free(event, flavor='raw') + lltype.free(self.event, flavor='raw') + RSDL.Quit() return 0 + + + def poll_event(self): + ok = rffi.cast(lltype.Signed, RSDL.PollEvent(self.event)) + return ok > 0 + + def check_for_escape(self): + c_type = rffi.getintfield(self.event, 'c_type') + if c_type == RSDL.KEYDOWN: + p = rffi.cast(RSDL.KeyboardEventPtr, self.event) + if rffi.getintfield(p.c_keysym, 'c_sym') == RSDL.K_ESCAPE: + return True + return False + # VIDEO DRIVER ----------------------------------------------------------------- @@ -49,21 +65,23 @@ def __init__(self): VideoDriver.__init__(self) + self.create_screen() self.map = [] - def set_window_size(self): + def create_screen(self): self.screen = RSDL.SetVideoMode(self.width, self.height, 32, 0) def update_display(self): - RSDL.LockSurface(screen) + RSDL.LockSurface(self.screen) self.draw_pixels() - RSDL.UnlockSurface(screen) - RSDL.Flip(screen) - + RSDL.UnlockSurface(self.screen) + RSDL.Flip(self.screen) + pass + def draw_pixels(self): for x in range(self.width): for y in range(self.height): - RSDL_helper.set_pixel(screen, x, y, self.get_pixel_color(x, y)) + RSDL_helper.set_pixel(self.screen, x, y, self.get_pixel_color(x, y)) def get_pixel_color(self, x, y): return self.pixels[x+self.width*y] @@ -81,56 +99,52 @@ def __init__(self): JoypadDriver.__init__(self) - self.last_char = "" + self.last_key = 0 def update(self, event): # fetch the event from sdl - ok = RSDL.WaitEvent(event) - assert rffi.cast(lltype.Signed, ok) == 1 type = rffi.getintfield(event, 'c_type') + print "JoypadDriver.update ", type if type == RSDL.KEYDOWN: - self.create_called_key() + self.create_called_key(event) self.on_key_down() elif type == RSDL.KEYUP: - self.create_called_key() + self.create_called_key(event) self.on_key_up() + pass def create_called_key(self, event): p = rffi.cast(RSDL.KeyboardEventPtr, event) - char = rffi.getintfield(p.c_keysym, 'c_unicode') - self.last_char = unichr(char).encode('utf-8') - - - - def create_button_key_codes(self): - self.button_key_codes = {key.UP : (self.button_up), - key.RIGHT : (self.button_right), - key.DOWN : (self.button_down), - key.LEFT : (self.button_left), - key.ENTER : (self.button_start), - key.SPACE : (self.button_select), - key.A : (self.button_a), - key.B : (self.button_b)} - - def create_listeners(self): - self.win.on_key_press = self.on_key_press - self.win.on_key_release = self.on_key_press + self.last_key = rffi.getintfield(p.c_keysym, 'c_sym') - def on_key_press(self, symbol, modifiers): - pressButtonFunction = self.get_button_handler(symbol, modifiers) - if pressButtonFunction is not None: - pressButtonFunction(True) + def on_key_down(self): + self.toggleButton(self.get_button_handler(self.last_key), True) + + def on_key_up(self): + self.toggleButton(self.get_button_handler(self.last_key), False) - def on_key_release(self, symbol, modifiers): - pressButtonFunction = self.get_button_handler(symbol, modifiers) + def toggleButton(self, pressButtonFunction, enabled): if pressButtonFunction is not None: - pressButtonFunction(False) - - def get_button_handler(self, symbol, modifiers): - if symbol in self.button_key_codes: - if len(self.button_key_codes[symbol]) == 1 or\ - self.button_key_codes[symbol][1] == modifiers: - return self.button_key_codes[symbol][0] + pressButtonFunction(self, enabled) + + def get_button_handler(self, key): + print "get_button_handler: ", key + if key == RSDL.K_UP: + return JoypadDriver.button_up + elif key == RSDL.K_RIGHT: + return JoypadDriver.button_right + elif key == RSDL.K_DOWN: + return JoypadDriver.button_down + elif key == RSDL.K_LEFT: + return JoypadDriver.button_left + elif key == RSDL.K_RETURN: + return JoypadDriver.button_start + elif key == RSDL.K_SPACE: + return JoypadDriver.button_select + elif key == RSDL.K_a: + return JoypadDriver.button_a + elif key == RSDL.K_b: + return JoypadDriver.button_b return None @@ -163,6 +177,8 @@ def entry_point(args=None): gameboy = GameBoyImplementation() + if args is None: + gameboy.load() # add return statement... return 0 From hpk at codespeak.net Tue May 20 17:50:27 2008 From: hpk at codespeak.net (hpk at codespeak.net) Date: Tue, 20 May 2008 17:50:27 +0200 (CEST) Subject: [pypy-svn] r55021 - pypy/django/tests Message-ID: <20080520155027.60863168462@codespeak.net> Author: hpk Date: Tue May 20 17:50:26 2008 New Revision: 55021 Modified: pypy/django/tests/runtests.py Log: improve error reporting Modified: pypy/django/tests/runtests.py ============================================================================== --- pypy/django/tests/runtests.py (original) +++ pypy/django/tests/runtests.py Tue May 20 17:50:26 2008 @@ -64,7 +64,7 @@ try: module = load_app(self.model_label) except Exception, e: - self.fail('Unable to load invalid model module') + self.fail('Unable to load invalid model module %r' % (self.model_label,)) # Make sure sys.stdout is not a tty so that we get errors without # coloring attached (makes matching the results easier). We restore From cami at codespeak.net Tue May 20 17:52:40 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Tue, 20 May 2008 17:52:40 +0200 (CEST) Subject: [pypy-svn] r55022 - pypy/dist/pypy/translator/goal Message-ID: <20080520155240.F3778168462@codespeak.net> Author: cami Date: Tue May 20 17:52:40 2008 New Revision: 55022 Modified: pypy/dist/pypy/translator/goal/targetgbimplementation.py Log: added extended key feedback Modified: pypy/dist/pypy/translator/goal/targetgbimplementation.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetgbimplementation.py (original) +++ pypy/dist/pypy/translator/goal/targetgbimplementation.py Tue May 20 17:52:40 2008 @@ -12,10 +12,10 @@ filename = argv[1] else: filename = ROM_PATH+"/rom9/rom9.gb" - print "using file: ", str(filename) + print "loading rom: ", str(filename) gameBoy = GameBoyImplementation() - gameBoy.load_cartridge_file(ROM_PATH+"/rom4/rom4.gb") - gameBoy.emulate(EMULATION_CYCLES) + gameBoy.load_cartridge_file(str(filename)) + gameBoy.mainLoop() return 0 From antocuni at codespeak.net Tue May 20 17:54:17 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 20 May 2008 17:54:17 +0200 (CEST) Subject: [pypy-svn] r55023 - pypy/django/tests Message-ID: <20080520155417.14F2B168462@codespeak.net> Author: antocuni Date: Tue May 20 17:54:16 2008 New Revision: 55023 Added: pypy/django/tests/testcount Log: the numer of tests actually ran for each modelname Added: pypy/django/tests/testcount ============================================================================== --- (empty file) +++ pypy/django/tests/testcount Tue May 20 17:54:16 2008 @@ -0,0 +1,97 @@ +admin 0 +auth 1 +comments 2 +contenttypes 1 +flatpages 0 +formtools 4 +markup 3 +redirects 0 +sessions 1 +sites 0 +webdesign 1 +auth_backends 1 +backends 1 +bug639 1 +cache 13 +datastructures 1 +datatypes 1 +dateformat 1 +db_typecasts 1 +decorators 1 +defaultfilters 1 +dispatch 16 +fixtures_regress 1 +forms 28 +httpwrappers 1 +humanize 5 +i18n 3 +initial_sql_regress 0 +invalid_admin_options 1 +many_to_one_regress 1 +maxlength 1 +max_lengths 3 +middleware 7 +model_fields 2 +model_regress 1 +null_queries 1 +one_to_one_regress 1 +queries 1 +requests 1 +serializers_regress 8 +string_lookup 1 +syndication 1 +templates 4 +test_client_regress 19 +text 1 +urlpatterns_reverse 1 +utils 10 +views 14 +basic 1 +choices 1 +custom_columns 1 +custom_managers 1 +custom_methods 1 +custom_pk 1 +empty 1 +field_defaults 1 +field_subclassing 1 +fixtures 2 +generic_relations 1 +get_latest 1 +get_object_or_404 1 +get_or_create 1 +invalid_models 1 +lookup 1 +m2m_and_m2o 1 +m2m_intermediary 1 +m2m_multiple 1 +m2m_recursive 1 +m2o_recursive 1 +m2o_recursive2 1 +manipulators 1 +many_to_many 1 +many_to_one 1 +many_to_one_null 1 +model_forms 1 +model_inheritance 1 +mutually_referential 1 +one_to_one 1 +ordering 1 +order_with_respect_to 1 +or_lookups 1 +pagination 1 +properties 1 +reserved_names 1 +reverse_lookup 1 +save_delete_hooks 1 +select_related 1 +serializers 1 +signals 1 +str 1 +test_client 31 +transactions 1 +update 1 +user_commands 1 +validation 1 +---------------- +Total 244 \ No newline at end of file From hpk at codespeak.net Tue May 20 18:02:05 2008 From: hpk at codespeak.net (hpk at codespeak.net) Date: Tue, 20 May 2008 18:02:05 +0200 (CEST) Subject: [pypy-svn] r55024 - pypy/django/tests Message-ID: <20080520160205.49B6916846C@codespeak.net> Author: hpk Date: Tue May 20 18:02:03 2008 New Revision: 55024 Modified: pypy/django/tests/conftest.py Log: actually it is not working Modified: pypy/django/tests/conftest.py ============================================================================== --- pypy/django/tests/conftest.py (original) +++ pypy/django/tests/conftest.py Tue May 20 18:02:03 2008 @@ -135,14 +135,15 @@ class DjangoInvalidModelTestCase(py.test.collect.Item): def run(self): - return - testcase = InvalidModelTestCase(self.parent.name) + basedir = self.fspath.dirpath().basename + name = basedir + "." + self.parent.name + testcase = InvalidModelTestCase(name) try: run_testcase_method(testcase) finally: from django.conf import settings - basedir = self.fspath.dirpath().basename - settings.INSTALLED_APPS.remove(basedir + "." + self.parent.name) + #print settings.INSTALLED_APPS + #settings.INSTALLED_APPS.remove(name) class DjangoUnitTest(py.test.collect.Item): def run(self): @@ -239,6 +240,8 @@ from django.db.models.loading import get_apps, load_app get_apps() +# XXX setup() should be called somewhere in the test process +# setup/teardown, not implicitely in loading a conftest.py setup() From tverwaes at codespeak.net Tue May 20 18:06:57 2008 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Tue, 20 May 2008 18:06:57 +0200 (CEST) Subject: [pypy-svn] r55025 - in pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk: . test Message-ID: <20080520160657.58DC0168404@codespeak.net> Author: tverwaes Date: Tue May 20 18:06:54 2008 New Revision: 55025 Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_shadow.py Log: (cfbolz, tverwaes) assuring consistency between before attaching shadows and after detaching them Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py Tue May 20 18:06:54 2008 @@ -347,7 +347,7 @@ # tempframe start # Stackpointer from smalltalk world == stacksize in python world self.store_stackpointer(utility.unwrap_int(w_sp1) - - self.w_method().tempframesize()) + self.tempframesize()) # TODO test def store_stackpointer(self, size): @@ -359,8 +359,8 @@ self._stack.extend(add) def wrap_stackpointer(self): - return utility.wrap_int(len(self._stack) + - self.w_method().tempframesize()) + return utility.wrap_int(len(self._stack) + + self.tempframesize()) # TODO test def external_stackpointer(self): @@ -482,6 +482,10 @@ del self._stack[start:] return res + def stackend(self): + # XXX this is incorrect when there is subclassing + return self._w_self_size + class BlockContextShadow(ContextPartShadow): @staticmethod @@ -513,18 +517,18 @@ if n0 == constants.BLKCTX_HOME_INDEX: return self.store_w_home(w_value) if n0 == constants.BLKCTX_INITIAL_IP_INDEX: - return self.uwrap_store_initialip(w_value) + return self.unwrap_store_initialip(w_value) if n0 == constants.BLKCTX_BLOCK_ARGUMENT_COUNT_INDEX: return self.unwrap_store_eargc(w_value) else: - return ContextPartShadow.fetch(self, n0) + return ContextPartShadow.store(self, n0, w_value) def attach_shadow(self): # Make sure the home context is updated first self.copy_from_w_self(constants.BLKCTX_HOME_INDEX) ContextPartShadow.attach_shadow(self) - def store_unwrap_initialip(self, w_value): + def unwrap_store_initialip(self, w_value): initialip = utility.unwrap_int(w_value) initialip -= 1 + self.w_method().getliteralsize() self.store_initialip(initialip) @@ -568,6 +572,10 @@ def stackpointer_offset(self): return constants.BLKCTX_STACK_START + def tempframesize(self): + # A blockcontext doesn't have any temps + return 0 + class MethodContextShadow(ContextPartShadow): def __init__(self, w_self): from pypy.lang.smalltalk import objtable @@ -637,6 +645,9 @@ self._temps = [objtable.w_nil] * self.w_method().tempframesize() ContextPartShadow.attach_shadow(self) + def tempframesize(self): + return self.w_method().tempframesize() + def w_method(self): return self._w_method @@ -668,7 +679,3 @@ def stackstart(self): return (constants.MTHDCTX_TEMP_FRAME_START + self.w_method().tempframesize()) - - def stackend(self): - # XXX this is incorrect when there is subclassing - return self._w_self_size Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_shadow.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_shadow.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_shadow.py Tue May 20 18:06:54 2008 @@ -91,6 +91,18 @@ w_object.store(constants.MTHDCTX_TEMP_FRAME_START, 'el') return w_object +def blockcontext(w_sender=objtable.w_nil, pc=1, stackpointer=1, stacksize=5, + home=methodcontext()): + w_object = model.W_PointersObject(classtable.w_MethodContext, constants.MTHDCTX_TEMP_FRAME_START+stacksize) + w_object.store(constants.CTXPART_SENDER_INDEX, w_sender) + w_object.store(constants.CTXPART_PC_INDEX, utility.wrap_int(pc)) + w_object.store(constants.CTXPART_STACKP_INDEX, utility.wrap_int(stackpointer)) + w_object.store(constants.BLKCTX_BLOCK_ARGUMENT_COUNT_INDEX, utility.wrap_int(54)) + w_object.store(constants.BLKCTX_INITIAL_IP_INDEX, utility.wrap_int(17)) + w_object.store(constants.BLKCTX_HOME_INDEX, home) + w_object.store(constants.BLKCTX_STACK_START, 'el') + return w_object + def test_context(): w_m = method() w_object = methodcontext(stackpointer=3, method=w_m) @@ -135,7 +147,7 @@ assert s_object.getbytecode() == 101 assert s_object.s_home() == s_object -def test_swap_shadows(): +def test_attach_detach_mc(): w_m = method() w_object = methodcontext(pc=13, method=w_m) old_vars = w_object._vars @@ -144,3 +156,12 @@ s_object.detach_shadow() assert w_object._vars == old_vars assert w_object._vars is not old_vars + +def test_attach_detach_bc(): + w_object = blockcontext(pc=13) + old_vars = w_object._vars + s_object = w_object.as_blockcontext_get_shadow() + assert w_object._vars is None + s_object.detach_shadow() + assert w_object._vars == old_vars + assert w_object._vars is not old_vars From arigo at codespeak.net Tue May 20 18:12:29 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 20 May 2008 18:12:29 +0200 (CEST) Subject: [pypy-svn] r55026 - pypy/branch/hybrid-io/pypy/rpython/lltypesystem Message-ID: <20080520161229.D9CF5168405@codespeak.net> Author: arigo Date: Tue May 20 18:12:28 2008 New Revision: 55026 Modified: pypy/branch/hybrid-io/pypy/rpython/lltypesystem/rbuilder.py Log: (fijal, arigo) Tweak the reallocation logic to grow geometrically, like e.g. the reallocation of lists. Modified: pypy/branch/hybrid-io/pypy/rpython/lltypesystem/rbuilder.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/lltypesystem/rbuilder.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/lltypesystem/rbuilder.py Tue May 20 18:12:28 2008 @@ -5,13 +5,27 @@ string_repr, unichar_repr, unicode_repr from pypy.rpython.annlowlevel import llstr from pypy.rlib import rgc +from pypy.rlib.rarithmetic import ovfcheck from pypy.rpython.lltypesystem.lltype import staticAdtMethod from pypy.tool.sourcetools import func_with_new_name +GROW_FAST_UNTIL = 100*1024*1024 # 100 MB + def new_grow_func(name): def stringbuilder_grow(ll_builder, needed): - # XXX tweak overallocation scheme - new_allocated = ll_builder.allocated + needed + 100 + allocated = ll_builder.allocated + if allocated < GROW_FAST_UNTIL: + new_allocated = allocated << 1 + else: + extra_size = allocated >> 2 + try: + new_allocated = ovfcheck(allocated + extra_size) + except OverflowError: + raise MemoryError + try: + new_allocated = ovfcheck(new_allocated + needed) + except OverflowError: + raise MemoryError ll_builder.buf = rgc.resize_buffer(ll_builder.buf, ll_builder.used, new_allocated) ll_builder.allocated = new_allocated From antocuni at codespeak.net Tue May 20 18:12:40 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 20 May 2008 18:12:40 +0200 (CEST) Subject: [pypy-svn] r55027 - pypy/django/tests Message-ID: <20080520161240.41DC8168445@codespeak.net> Author: antocuni Date: Tue May 20 18:12:39 2008 New Revision: 55027 Modified: pypy/django/tests/conftest.py Log: clean both the cache and the INSTALLED_APPS after having ran an invalid model test Modified: pypy/django/tests/conftest.py ============================================================================== --- pypy/django/tests/conftest.py (original) +++ pypy/django/tests/conftest.py Tue May 20 18:12:39 2008 @@ -142,8 +142,11 @@ run_testcase_method(testcase) finally: from django.conf import settings - #print settings.INSTALLED_APPS - #settings.INSTALLED_APPS.remove(name) + from django.db.models.loading import cache + if name in settings.INSTALLED_APPS: + settings.INSTALLED_APPS.remove(name) + if self.parent.name in cache.app_models: + del cache.app_models[self.parent.name] class DjangoUnitTest(py.test.collect.Item): def run(self): From arigo at codespeak.net Tue May 20 18:13:02 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 20 May 2008 18:13:02 +0200 (CEST) Subject: [pypy-svn] r55028 - in pypy/branch/hybrid-io/pypy/rpython: lltypesystem memory/gctransform Message-ID: <20080520161302.C3DA4168405@codespeak.net> Author: arigo Date: Tue May 20 18:13:00 2008 New Revision: 55028 Modified: pypy/branch/hybrid-io/pypy/rpython/lltypesystem/lloperation.py pypy/branch/hybrid-io/pypy/rpython/memory/gctransform/framework.py pypy/branch/hybrid-io/pypy/rpython/memory/gctransform/transform.py Log: (fijal, arigo, pedronis around) Fix two missing insertions of push_roots/pop_roots. Modified: pypy/branch/hybrid-io/pypy/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/lltypesystem/lloperation.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/lltypesystem/lloperation.py Tue May 20 18:13:00 2008 @@ -326,7 +326,7 @@ 'malloc_nonmovable': LLOp(canraise=(MemoryError,), canunwindgc=True), 'malloc_nonmovable_varsize':LLOp(canraise=(MemoryError,),canunwindgc=True), 'malloc_resizable_buffer': LLOp(canraise=(MemoryError,),canunwindgc=True), - 'resize_buffer': LLOp(canraise=(MemoryError,)), + 'resize_buffer': LLOp(canraise=(MemoryError,), canunwindgc=True), 'finish_building_buffer' : LLOp(canraise=(MemoryError,), canunwindgc=True), 'zero_gc_pointers_inside': LLOp(), 'free': LLOp(), Modified: pypy/branch/hybrid-io/pypy/rpython/memory/gctransform/framework.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/memory/gctransform/framework.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/memory/gctransform/framework.py Tue May 20 18:13:00 2008 @@ -507,7 +507,8 @@ args = [self.c_const_gc, c_type_id, v_length, c_size, c_varitemsize, c_ofstolength, c_can_collect, c_has_finalizer] - livevars = self.push_roots(hop) + keep_current_args = flags.get('keep_current_args', False) + livevars = self.push_roots(hop, keep_current_args=keep_current_args) v_result = hop.genop("direct_call", [malloc_ptr] + args, resulttype=llmemory.GCREF) self.pop_roots(hop, livevars) @@ -536,10 +537,7 @@ c_itemsize, c_lengthofs, c_grow): vlist = [self.realloc_ptr, self.c_const_gc, v_ptr, v_newsize, c_const_size, c_itemsize, c_lengthofs, c_grow] - if c_grow.value: - livevars = [] # collection not possible if grow=True - else: - livevars = self.push_roots(hop) + livevars = self.push_roots(hop) v_result = hop.genop('direct_call', vlist, resulttype=llmemory.GCREF) self.pop_roots(hop, livevars) Modified: pypy/branch/hybrid-io/pypy/rpython/memory/gctransform/transform.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/memory/gctransform/transform.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/memory/gctransform/transform.py Tue May 20 18:13:00 2008 @@ -579,7 +579,7 @@ def _gct_resize_buffer_no_realloc(self, hop, v_lgt): op = hop.spaceop meth = self.gct_fv_gc_malloc_varsize - flags = {'flavor':'gc', 'varsize': True} + flags = {'flavor':'gc', 'varsize': True, 'keep_current_args': True} self.varsize_malloc_helper(hop, flags, meth, []) # fish resvar v_newbuf = hop.llops[-1].result From antocuni at codespeak.net Tue May 20 18:15:22 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 20 May 2008 18:15:22 +0200 (CEST) Subject: [pypy-svn] r55029 - pypy/django/tests Message-ID: <20080520161522.0A05316840F@codespeak.net> Author: antocuni Date: Tue May 20 18:15:21 2008 New Revision: 55029 Modified: pypy/django/tests/testcount Log: specify where do they come from Modified: pypy/django/tests/testcount ============================================================================== --- pypy/django/tests/testcount (original) +++ pypy/django/tests/testcount Tue May 20 18:15:21 2008 @@ -1,3 +1,4 @@ +# contrib admin 0 auth 1 comments 2 @@ -9,6 +10,8 @@ sessions 1 sites 0 webdesign 1 + +# regressiontest auth_backends 1 backends 1 bug639 1 @@ -46,6 +49,8 @@ urlpatterns_reverse 1 utils 10 views 14 + +# modeltest basic 1 choices 1 custom_columns 1 From antocuni at codespeak.net Tue May 20 18:15:56 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 20 May 2008 18:15:56 +0200 (CEST) Subject: [pypy-svn] r55030 - pypy/django/tests Message-ID: <20080520161556.4B06E16840F@codespeak.net> Author: antocuni Date: Tue May 20 18:15:55 2008 New Revision: 55030 Modified: pypy/django/tests/testcount Log: correct total Modified: pypy/django/tests/testcount ============================================================================== --- pypy/django/tests/testcount (original) +++ pypy/django/tests/testcount Tue May 20 18:15:55 2008 @@ -99,4 +99,4 @@ user_commands 1 validation 1 ---------------- -Total 244 \ No newline at end of file +Total 246 \ No newline at end of file From fijal at codespeak.net Tue May 20 18:21:18 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 20 May 2008 18:21:18 +0200 (CEST) Subject: [pypy-svn] r55031 - pypy/branch/hybrid-io/pypy/objspace/std Message-ID: <20080520162118.13313168433@codespeak.net> Author: fijal Date: Tue May 20 18:21:17 2008 New Revision: 55031 Modified: pypy/branch/hybrid-io/pypy/objspace/std/formatting.py pypy/branch/hybrid-io/pypy/objspace/std/stringobject.py Log: Some estimates for formatting. Modified: pypy/branch/hybrid-io/pypy/objspace/std/formatting.py ============================================================================== --- pypy/branch/hybrid-io/pypy/objspace/std/formatting.py (original) +++ pypy/branch/hybrid-io/pypy/objspace/std/formatting.py Tue May 20 18:21:17 2008 @@ -256,10 +256,11 @@ return result def format(self): + lgt = len(self.fmt) + 4 * len(self.values_w) + 10 if do_unicode: - result = UnicodeBuilder() + result = UnicodeBuilder(lgt) else: - result = StringBuilder() + result = StringBuilder(lgt) self.result = result while True: # fast path: consume as many characters as possible Modified: pypy/branch/hybrid-io/pypy/objspace/std/stringobject.py ============================================================================== --- pypy/branch/hybrid-io/pypy/objspace/std/stringobject.py (original) +++ pypy/branch/hybrid-io/pypy/objspace/std/stringobject.py Tue May 20 18:21:17 2008 @@ -861,7 +861,7 @@ def repr__String(space, w_str): s = w_str._value - buf = StringBuilder(50) # XXX this needs to be constant, fix + buf = StringBuilder(len(s) + 10) quote = "'" if quote in s and '"' not in s: From cfbolz at codespeak.net Tue May 20 18:24:47 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 20 May 2008 18:24:47 +0200 (CEST) Subject: [pypy-svn] r55032 - pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk Message-ID: <20080520162447.4688E168452@codespeak.net> Author: cfbolz Date: Tue May 20 18:24:46 2008 New Revision: 55032 Added: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/running-something-mini.image (contents, props changed) Log: add an image that will run 1 + 2 when resuming it Added: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/running-something-mini.image ============================================================================== Binary file. No diff available. From hpk at codespeak.net Tue May 20 18:30:15 2008 From: hpk at codespeak.net (hpk at codespeak.net) Date: Tue, 20 May 2008 18:30:15 +0200 (CEST) Subject: [pypy-svn] r55033 - pypy/django/tests Message-ID: <20080520163015.3190F168452@codespeak.net> Author: hpk Date: Tue May 20 18:30:14 2008 New Revision: 55033 Modified: pypy/django/tests/conftest.py Log: (anto, hpk) try to find all of the doctests which works but some of them fail with obscure unicode stuff Modified: pypy/django/tests/conftest.py ============================================================================== --- pypy/django/tests/conftest.py (original) +++ pypy/django/tests/conftest.py Tue May 20 18:30:14 2008 @@ -93,8 +93,8 @@ return result def _find_doctests(self, mod): - if hasattr(mod, '__test__') and mod.__test__.get('API_TESTS'): - return ['%docstring%'] + if hasattr(mod, '__test__'): + return ["__test__[%s]" % x for x in mod.__test__.keys()] if os.path.basename(mod.__file__).startswith("tests") and mod.__doc__: return ['%docmodulestring%'] #return [)] @@ -119,11 +119,13 @@ if name == '%invalidtestcase%': return DjangoInvalidModelTestCase(name, self) mod = self._get_mod() - if name == '%docstring%': - return DocTestItem(self.fspath.basename + '.%docstring%', mod, mod.__test__['API_TESTS']) - elif name == 'tests.%docstring%': + if name.startswith("__test__["): + doctestname = name[9:-1] + return DocTestItem(name, mod, mod.__test__[doctestname]) + elif name.startswith('tests.__test__['): + doctestname = name[15:-1] mod = mod.tests - return DocTestItem(self.fspath.basename + '.%docstring%', mod, mod.__test__['API_TESTS']) + return DocTestItem(name, mod, mod.__test__[doctestname]) elif name == '%docmodulestring%': return DocTestItem(self.fspath.basename + '.%docstring%', mod, mod.__doc__) elif name == 'tests.%docmodulestring%': From arigo at codespeak.net Tue May 20 19:36:28 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 20 May 2008 19:36:28 +0200 (CEST) Subject: [pypy-svn] r55034 - in pypy/branch/hybrid-io/pypy/rpython/memory: . gc test Message-ID: <20080520173628.A29B91684F4@codespeak.net> Author: arigo Date: Tue May 20 19:36:26 2008 New Revision: 55034 Modified: pypy/branch/hybrid-io/pypy/rpython/memory/gc/hybrid.py pypy/branch/hybrid-io/pypy/rpython/memory/support.py pypy/branch/hybrid-io/pypy/rpython/memory/test/test_support.py Log: Use a remove() method on the AddressStack to cheaply locate and remove an address that we expect to be near the top. Modified: pypy/branch/hybrid-io/pypy/rpython/memory/gc/hybrid.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/memory/gc/hybrid.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/memory/gc/hybrid.py Tue May 20 19:36:26 2008 @@ -234,7 +234,7 @@ oldlength = (addr + lengthofs).signed[0] old_tot_size = size_gc_header + fixedsize + oldlength * itemsize source_addr = addr - size_gc_header - self._remove_addr_from_resizable_objects(addr) + self.gen2_resizable_objects.remove(addr) if grow: result = llop.raw_realloc_grow(llmemory.Address, source_addr, old_tot_size, tot_size) @@ -254,16 +254,6 @@ (result + size_gc_header + lengthofs).signed[0] = newlength return llmemory.cast_adr_to_ptr(result + size_gc_header, llmemory.GCREF) - def _remove_addr_from_resizable_objects(self, addr): - objects = self.gen2_resizable_objects - newstack = self.AddressStack() - while objects.non_empty(): - obj = objects.pop() - if obj != addr: - newstack.append(obj) - objects.delete() - self.gen2_resizable_objects = newstack - def can_move(self, addr): tid = self.header(addr).tid return not (tid & GCFLAG_EXTERNAL) Modified: pypy/branch/hybrid-io/pypy/rpython/memory/support.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/memory/support.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/memory/support.py Tue May 20 19:36:26 2008 @@ -138,6 +138,22 @@ self.foreach(_add_in_dict, result) return result + def remove(self, addr): + """Remove 'addr' from the stack. The addr *must* be in the list, + and preferrably near the top. + """ + got = self.pop() + chunk = self.chunk + count = self.used_in_last_chunk + while got != addr: + count -= 1 + if count < 0: + chunk = chunk.next + count = chunk_size - 1 + next = chunk.items[count] + chunk.items[count] = got + got = next + cache[chunk_size] = AddressStack return AddressStack Modified: pypy/branch/hybrid-io/pypy/rpython/memory/test/test_support.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/memory/test/test_support.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/memory/test/test_support.py Tue May 20 19:36:26 2008 @@ -78,6 +78,22 @@ ll.foreach(callback, 42) assert seen == addrs or seen[::-1] == addrs # order not guaranteed + def test_remove(self): + AddressStack = get_address_stack() + addrs = [raw_malloc(llmemory.sizeof(lltype.Signed)) + for i in range(2200)] + ll = AddressStack() + for i in range(2200): + ll.append(addrs[i]) + ll.remove(addrs[-400]) + expected = range(2200) + del expected[-400] + expected.reverse() + for i in expected: + a = ll.pop() + assert a == addrs[i] + assert not ll.non_empty() + class TestAddressDeque: def test_big_access(self): From cami at codespeak.net Tue May 20 19:58:19 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Tue, 20 May 2008 19:58:19 +0200 (CEST) Subject: [pypy-svn] r55035 - in pypy/dist/pypy/lang/gameboy: . test Message-ID: <20080520175819.0FA25168433@codespeak.net> Author: cami Date: Tue May 20 19:58:17 2008 New Revision: 55035 Added: pypy/dist/pypy/lang/gameboy/test/test_memory_bank_controller.py Modified: pypy/dist/pypy/lang/gameboy/cartridge.py pypy/dist/pypy/lang/gameboy/cpu.py pypy/dist/pypy/lang/gameboy/gameboy.py pypy/dist/pypy/lang/gameboy/gameboyImplementation.py pypy/dist/pypy/lang/gameboy/test/test_rom.py Log: created memory bank controller added debug prints for the cpu fixed some variable bug in cartrdge Modified: pypy/dist/pypy/lang/gameboy/cartridge.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/cartridge.py (original) +++ pypy/dist/pypy/lang/gameboy/cartridge.py Tue May 20 19:58:17 2008 @@ -149,6 +149,7 @@ return (checksum == self.get_header_checksum()) def create_bank_controller(self, type, rom, ram, clock_driver): + print "create_bank_controller: ", type return MEMORY_BANK_MAPPING[type](rom, ram, clock_driver) @@ -252,28 +253,28 @@ self.set_ram(ram) def reset(self): - self.rom_bank = constants.ROM_BANK_SIZE - self.ram_bank = 0 + self.rom_bank = constants.ROM_BANK_SIZE + self.ram_bank = 0 self.ram_enable = False - self.rom = [] - self.ram = [] - self.rom_size = 0 - self.ram_size = 0 + self.rom = [] + self.ram = [] + self.rom_size = 0 + self.ram_size = 0 def set_rom(self, buffer): - banks = len(buffer) / constants.ROM_BANK_SIZE + banks = int(len(buffer) / constants.ROM_BANK_SIZE) if banks < self.min_rom_bank_size or banks > self.max_rom_bank_size: - raise Exception("Invalid constants.ROM size") + raise Exception("Invalid ROM size %s" % hex(len(buffer))) self.rom = buffer - self.rom_size = constants.ROM_BANK_SIZE*banks - 1 + self.rom_size = constants.ROM_BANK_SIZE * banks - 1 def set_ram(self, buffer): - banks = len(buffer) / constants.RAM_BANK_SIZE + banks = int(len(buffer) / constants.RAM_BANK_SIZE) if banks < self.min_ram_bank_size or banks > self.max_ram_bank_size: - raise Exception("Invalid constants.RAM size") + raise Exception("Invalid RAM size %s" % hex(len(buffer))) self.ram = buffer - self.ram_size = constants.RAM_BANK_SIZE*banks - 1 + self.ram_size = constants.RAM_BANK_SIZE * banks - 1 def read(self, address): @@ -286,7 +287,7 @@ raise Exception("MBC: Invalid address, out of range") def write(self, address, data): - pass + raise Exception("MBC: Invalid write access") #------------------------------------------------------------------------------- @@ -337,10 +338,13 @@ self.memory_model = data & 0x01 elif address >= 0xA000 and address <= 0xBFFF and self.ram_enable: # A000-BFFF self.ram[self.ram_bank + (address & 0x1FFF)] = data + else: + raise Exception("Invalid memory Access") def write_ram_enable(self, address, data): if self.ram_size > 0: self.ram_enable = ((data & 0x0A) == 0x0A) + print "write_ram_enable: ", hex(self.ram_enable) def write_rom_bank_1(self, address, data): if (data & 0x1F) == 0: Modified: pypy/dist/pypy/lang/gameboy/cpu.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/cpu.py (original) +++ pypy/dist/pypy/lang/gameboy/cpu.py Tue May 20 19:58:17 2008 @@ -355,9 +355,13 @@ def fetch_execute(self): # Execution - FETCH_EXECUTE_OP_CODES[self.fetch()](self) + opCode = self.fetch() + print " fetch exe:", hex(opCode) + FETCH_EXECUTE_OP_CODES[opCode](self) def execute(self, opCode): + print "-"*60 + print "exe: ", hex(opCode), "|", hex(self.pc.get()), hex(self.sp.get()) OP_CODES[opCode](self) def read(self, hi, lo=None): @@ -369,6 +373,7 @@ return self.memory.read(address) def write(self, address, data): + print " write: ", "a:", hex(address), "v:", hex(data) # 2 cycles self.memory.write(address, data) self.cycles -= 2 @@ -381,6 +386,7 @@ else: data = self.memory.read(self.pc.get(use_cycles)) self.pc.inc(use_cycles) # 2 cycles + print " fetch: ", data return data def fetch_double_address(self): Modified: pypy/dist/pypy/lang/gameboy/gameboy.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/gameboy.py (original) +++ pypy/dist/pypy/lang/gameboy/gameboy.py Tue May 20 19:58:17 2008 @@ -93,6 +93,8 @@ self.video.emulate(count) self.sound.emulate(count) self.joypad.emulate(count) + if count == 0: + break ticks -= count return 0 @@ -108,32 +110,48 @@ raise Exception("invalid read address given") return receiver.read(address) + def print_receiver_msg(self, address, name): + print " mem.receiver ", hex(address), name + def get_receiver(self, address): if 0x0000 <= address <= 0x7FFF: + self.print_receiver_msg(address, "memoryBank") return self.cartridge_manager.get_memory_bank() elif 0x8000 <= address <= 0x9FFF: + self.print_receiver_msg(address, "video") return self.video elif 0xA000 <= address <= 0xBFFF: + self.print_receiver_msg(address, "memoryBank") return self.cartridge_manager.get_memory_bank() elif 0xC000 <= address <= 0xFDFF: + self.print_receiver_msg(address, "ram") return self.ram elif 0xFE00 <= address <= 0xFEFF: + self.print_receiver_msg(address, "video") return self.video elif 0xFF00 <= address <= 0xFF00: + self.print_receiver_msg(address, "joypad") return self.joypad elif 0xFF01 <= address <= 0xFF02: + self.print_receiver_msg(address, "serial") return self.serial elif 0xFF04 <= address <= 0xFF07: + self.print_receiver_msg(address, "timer") return self.timer elif 0xFF0F <= address <= 0xFF0F: + self.print_receiver_msg(address, "interrupt") return self.interrupt elif 0xFF10 <= address <= 0xFF3F: + self.print_receiver_msg(address, "sound") return self.sound elif 0xFF40 <= address <= 0xFF4B: + self.print_receiver_msg(address, "video") return self.video elif 0xFF80 <= address <= 0xFFFE: + self.print_receiver_msg(address, "ram") return self.ram elif 0xFFFF <= address <= 0xFFFF: + self.print_receiver_msg(address, "interrupt") return self.interrupt def draw_logo(self): Modified: pypy/dist/pypy/lang/gameboy/gameboyImplementation.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/gameboyImplementation.py (original) +++ pypy/dist/pypy/lang/gameboy/gameboyImplementation.py Tue May 20 19:58:17 2008 @@ -1,5 +1,4 @@ #!/usr/bin/env python -import time from pypy.lang.gameboy.gameboy import GameBoy from pypy.lang.gameboy.joypad import JoypadDriver @@ -9,7 +8,7 @@ from pypy.rlib.rsdl import RSDL, RSDL_helper from pypy.rpython.lltypesystem import lltype, rffi from pypy.rlib.objectmodel import specialize - +import py # GAMEBOY ---------------------------------------------------------------------- @@ -18,7 +17,6 @@ def __init__(self): GameBoy.__init__(self) self.init_sdl() - self.mainLoop() def init_sdl(self): assert RSDL.Init(RSDL.INIT_VIDEO) >= 0 @@ -38,8 +36,8 @@ if self.check_for_escape(): break self.joypad_driver.update(self.event) - #self.emulate(5) - #time.sleep(0.01) + self.emulate(10) + RSDL.Delay(10) finally: lltype.free(self.event, flavor='raw') RSDL.Quit() @@ -117,10 +115,12 @@ p = rffi.cast(RSDL.KeyboardEventPtr, event) self.last_key = rffi.getintfield(p.c_keysym, 'c_sym') - def on_key_down(self): + def on_key_down(self): + print "press" self.toggleButton(self.get_button_handler(self.last_key), True) def on_key_up(self): + print "release" self.toggleButton(self.get_button_handler(self.last_key), False) def toggleButton(self, pressButtonFunction, enabled): @@ -128,22 +128,29 @@ pressButtonFunction(self, enabled) def get_button_handler(self, key): - print "get_button_handler: ", key if key == RSDL.K_UP: + print " up" return JoypadDriver.button_up elif key == RSDL.K_RIGHT: + print " right" return JoypadDriver.button_right elif key == RSDL.K_DOWN: + print " down" return JoypadDriver.button_down elif key == RSDL.K_LEFT: + print " left" return JoypadDriver.button_left elif key == RSDL.K_RETURN: + print " start" return JoypadDriver.button_start elif key == RSDL.K_SPACE: + print " select" return JoypadDriver.button_select elif key == RSDL.K_a: + print " A" return JoypadDriver.button_a elif key == RSDL.K_b: + print " B" return JoypadDriver.button_b return None @@ -175,11 +182,20 @@ # ============================================================================== -def entry_point(args=None): +ROM_PATH = str(py.magic.autopath().dirpath().dirpath().dirpath())+"/lang/gameboy/rom" +import pdb + +def entry_point(argv=None): + print "startin gameboy emulation" gameboy = GameBoyImplementation() - if args is None: - gameboy.load() - # add return statement... + if argv is not None and len(argv) > 1: + filename = argv[1] + else: + #filename = gameboy.load() + filename = ROM_PATH+"/rom9/rom9.gb" + print "loading rom: ", str(filename) + gameboy.load_cartridge_file(str(filename)) + pdb.runcall(gameboy.mainLoop) return 0 @@ -188,5 +204,9 @@ def target(*args): return entry_point, None -if __name__ == '__main__': - entry_point() \ No newline at end of file +def test_target(): + entry_point() + + + + \ No newline at end of file Added: pypy/dist/pypy/lang/gameboy/test/test_memory_bank_controller.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/lang/gameboy/test/test_memory_bank_controller.py Tue May 20 19:58:17 2008 @@ -0,0 +1,105 @@ + +from pypy.lang.gameboy.cartridge import * +from pypy.lang.gameboy.timer import Clock +from pypy.lang.gameboy.constants import * +import py + +def get_clock_driver(): + return Clock() + +RAM_SIZE = 3 +ROM_SIZE = 2 + +def get_ram(): + return [0] * RAM_SIZE * constants.RAM_BANK_SIZE + +def get_rom(): + return [0xFF] * ROM_SIZE * constants.ROM_BANK_SIZE + + +def test_mbc_init(): + try: + MBC(get_ram(), get_rom(), get_clock_driver()) + py.test.fail("") + except: + pass + + try: + MBC(get_ram(), get_rom(), get_clock_driver(), 0, ROM_SIZE-1, 0, + RAM_SIZE-1) + py.test.fail("") + except: + pass + + try: + MBC(get_ram(), get_rom(), get_clock_driver(), ROM_SIZE+1, ROM_SIZE+1, + RAM_SIZE+1, RAM_SIZE+1) + py.test.fail("") + except: + pass + +def test_mbc(): + py.test.skip() + mbc = MBC(get_ram(), get_rom(), get_clock_driver(),1, 0xF3, 2, 0xF1) + assert mbc.min_rom_bank_size == 1 + assert mbc.max_rom_bank_size == 0xF3 + assert mbc.min_ram_bank_size == 2 + assert mbc.max_ram_bank_size == 0xF1 + assert mbc.rom_bank == constants.ROM_BANK_SIZE + assert mbc.ram_bank == 0 + assert mbc.ram_enable == False + assert mbc.rom_size == ROM_SIZE * constants.ROM_BANK_SIZE - 1 + assert mbc.ram_size == RAM_SIZE * constants.ROM_BANK_SIZE - 1 + assert len(mbc.rom) == ROM_SIZE + assert len(mbc.ram) == RAM_SIZE + + +def test_mbc_read_write(): + mbc = MBC([0]*0xFFFF,[0]*0xFFFF, get_clock_driver(),1, 0xFFFF, 2, 0xFFFF) + try: + mbc.write(0, 0) + py.test.fail(" MBC has an abstract write") + except: + pass + + try: + mbc.read(0x1FFFF+1) + py.test.fail(" write address to high") + except: + pass + +def test_mbc_read_write_test(mbc=None): + if mbc==None: + mbc = MBC([0]*0xFFFF,[0]*0xFFFF, get_clock_driver(),1, 0xFFFF, 2, 0xFFFF) + + value = 0x12 + mbc.rom[0x3FFF] = value + assert mbc.read(0x3FFF) == value + + mbc.rom[mbc.rom_bank] = value + assert mbc.read(0x4000) == value + + + mbc.ram[mbc.ram_bank] = value + mbc.ram_enable = False + try: + mbc.read(0xA000) + py.test.fail("ram is not enabled") + except: + pass + mbc.ram_enable = True + assert mbc.read(0xA000) == value + + + +def test_mbc1_write(): + py.test.skip("buggy implementation of MBC1++") + mbc1 = MBC1([0]*0x5FFF,[0]*0xBFFF, get_clock_driver()) + test_mbc_read_write_test(mbc1) + + + + + + + \ No newline at end of file Modified: pypy/dist/pypy/lang/gameboy/test/test_rom.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/test/test_rom.py (original) +++ pypy/dist/pypy/lang/gameboy/test/test_rom.py Tue May 20 19:58:17 2008 @@ -62,6 +62,7 @@ def test_rom7(): + py.test.skip("Current Default ROM Implemenation doesnt allow write") gameBoy = GameBoy() gameBoy.load_cartridge_file(ROM_PATH+"/rom7/rom7.gb") gameBoy.emulate(EMULATION_CYCLES) From tverwaes at codespeak.net Tue May 20 20:16:10 2008 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Tue, 20 May 2008 20:16:10 +0200 (CEST) Subject: [pypy-svn] r55036 - in pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk: . test Message-ID: <20080520181610.CCC3D1684ED@codespeak.net> Author: tverwaes Date: Tue May 20 20:16:09 2008 New Revision: 55036 Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/running-something-mini.image pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_miniimage.py Log: (cfbolz, tverwaes) adding tests for partly image continuating Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py Tue May 20 20:16:09 2008 @@ -319,8 +319,11 @@ def as_context_get_shadow(self): from pypy.lang.smalltalk.shadow import ContextPartShadow # XXX TODO should figure out itself if its method or block context - assert self._shadow is not None - return self.as_special_get_shadow(ContextPartShadow) + if self._shadow is None: + if ContextPartShadow.is_block_context(self): + return self.as_blockcontext_get_shadow() + return self.as_methodcontext_get_shadow() + return self._shadow def as_methoddict_get_shadow(self): from pypy.lang.smalltalk.shadow import MethodDictionaryShadow Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/running-something-mini.image ============================================================================== Binary files. No diff available. Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py Tue May 20 20:16:09 2008 @@ -308,7 +308,12 @@ self._stack = [] AbstractRedirectingShadow.__init__(self, w_self) - # TODO test + @staticmethod + def is_block_context(w_pointers): + from pypy.lang.smalltalk.classtable import w_SmallInteger + method_or_argc = w_pointers.fetch(constants.MTHDCTX_METHOD) + return method_or_argc.getclass().is_same_object(w_SmallInteger) + def fetch(self, n0): if n0 == constants.CTXPART_SENDER_INDEX: return self.w_sender() @@ -325,7 +330,6 @@ # XXX later should store tail out of known context part as well raise error.WrapperException("Index in context out of bounds") - # TODO test def store(self, n0, w_value): if n0 == constants.CTXPART_SENDER_INDEX: return self.store_w_sender(w_value) @@ -349,7 +353,6 @@ self.store_stackpointer(utility.unwrap_int(w_sp1) - self.tempframesize()) - # TODO test def store_stackpointer(self, size): from pypy.lang.smalltalk import objtable if size < len(self._stack): @@ -362,7 +365,6 @@ return utility.wrap_int(len(self._stack) + self.tempframesize()) - # TODO test def external_stackpointer(self): return len(self._stack) + self.stackstart() @@ -397,14 +399,12 @@ else: return w_sender.as_context_get_shadow() - # TODO test def store_unwrap_pc(self, w_pc): pc = utility.unwrap_int(w_pc) pc -= self.w_method().bytecodeoffset() pc -= 1 self.store_pc(pc) - # TODO test def wrap_pc(self): pc = self.pc() pc += 1 Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_miniimage.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_miniimage.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_miniimage.py Tue May 20 20:16:09 2008 @@ -12,11 +12,12 @@ from pypy.lang.smalltalk import utility # lazy initialization of test data, ie ImageReader and Float class -def setup_module(module): +def setup_module(module, filename='mini.image'): + # XXX XXX find a way to get rid of global state global mini_image global reader global image - mini_image = py.magic.autopath().dirpath().dirpath().join('mini.image') + mini_image = py.magic.autopath().dirpath().dirpath().join(filename) reader = open_miniimage() reader.initialize() image = squeakimage.SqueakImage() @@ -228,18 +229,10 @@ def test_runimage(): py.test.skip("This method actually runs an image. Fails since no graphical primitives yet") - from pypy.lang.smalltalk.shadow import SemaphoreShadow - s_semaphore = SemaphoreShadow(None) - s_scheduler = s_semaphore.s_scheduler() - s_ap = s_scheduler.s_active_process() - s_ctx = s_ap.w_suspended_context().as_methodcontext_get_shadow() - s_ap.store_w_suspended_context(objtable.w_nil) - - # XXX Important - # Push return value of snapshot primitive - # The interpreter must resume at the very moment the snapshot primitive - # returns. - s_ctx._stack = [objtable.w_true] + from pypy.lang.smalltalk import wrapper + ap = wrapper.ProcessWraper(wrapper.scheduler().active_process()) + s_ctx = ap.suspended_context().as_methodcontext_get_shadow() + ap.store_suspended_context(objtable.w_nil) interp = interpreter.Interpreter() interp.store_w_active_context(s_ctx.w_self()) @@ -285,3 +278,29 @@ #print interp.s_active_context.stack except interpreter.ReturnFromTopLevel, e: return e.object + +def test_step_forged_image(): + from pypy.lang.smalltalk import wrapper + ap = wrapper.ProcessWrapper(wrapper.scheduler().active_process()) + s_ctx = ap.suspended_context().as_context_get_shadow() + assert isinstance(s_ctx, shadow.BlockContextShadow) + assert s_ctx.top().is_same_object(objtable.w_true) + +def test_step_forged_image(): + setup_module(None, filename='running-something-mini.image') + from pypy.lang.smalltalk import wrapper + ap = wrapper.ProcessWrapper(wrapper.scheduler().active_process()) + s_ctx = ap.suspended_context().as_context_get_shadow() + ap.store_suspended_context(objtable.w_nil) + + interp = interpreter.Interpreter() + interp.store_w_active_context(s_ctx.w_self()) + assert isinstance(s_ctx, shadow.MethodContextShadow) + assert interp.s_active_context().top().is_same_object(objtable.w_true) + interp.step() + interp.step() + assert interp.s_active_context().top().value == 1 + interp.step() + assert interp.s_active_context().top().value == 2 + interp.step() + assert interp.s_active_context().top().value == 3 From cfbolz at codespeak.net Tue May 20 20:18:45 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 20 May 2008 20:18:45 +0200 (CEST) Subject: [pypy-svn] r55037 - pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk Message-ID: <20080520181845.179A31684ED@codespeak.net> Author: cfbolz Date: Tue May 20 20:18:44 2008 New Revision: 55037 Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/primitives.py Log: fix exception Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/primitives.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/primitives.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/primitives.py Tue May 20 20:18:44 2008 @@ -505,7 +505,7 @@ def func(interp, w_rcvr, w_new): if w_rcvr.become(w_new): return w_rcvr - raise PrimitiveNotYetWrittenError + raise PrimitiveFailedError def fake_bytes_left(): return utility.wrap_int(2**20) # XXX we don't know how to do this :-( From tverwaes at codespeak.net Tue May 20 20:41:49 2008 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Tue, 20 May 2008 20:41:49 +0200 (CEST) Subject: [pypy-svn] r55038 - pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk Message-ID: <20080520184149.1F9E4168452@codespeak.net> Author: tverwaes Date: Tue May 20 20:41:47 2008 New Revision: 55038 Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py Log: (cfbolz, tverwaes) adding translation fixes (typo + rangecheck) Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py Tue May 20 20:41:47 2008 @@ -147,7 +147,8 @@ w_realclass = w_self._fetch(w_self.size() - 1) assert isinstance(w_realclass, model.W_PointersObject) if w_realclass.size() > constants.CLASS_NAME_INDEX: - w_name = w_realclass.__fetch(onstants.CLASS_NAME_INDEX) + # TODO ADD TEST WHICH GOES OVER THIS PART + w_name = w_realclass._fetch(constants.CLASS_NAME_INDEX) if isinstance(w_name, model.W_BytesObject): self.name = w_name.as_string() @@ -356,6 +357,8 @@ def store_stackpointer(self, size): from pypy.lang.smalltalk import objtable if size < len(self._stack): + # TODO Warn back to user + assert size >= 0 self._stack = self._stack[:size] else: add = [objtable.w_nil] * (size - len(self._stack)) From cfbolz at codespeak.net Tue May 20 20:44:24 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 20 May 2008 20:44:24 +0200 (CEST) Subject: [pypy-svn] r55039 - pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk Message-ID: <20080520184424.6D5EB16853F@codespeak.net> Author: cfbolz Date: Tue May 20 20:44:21 2008 New Revision: 55039 Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py Log: fix translation bug Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py Tue May 20 20:44:21 2008 @@ -181,6 +181,8 @@ return isinstance(self.hash, int) def become(self, w_other): + if not isinstance(w_other, W_AbstractObjectWithIdentityHash): + return False self.hash, w_other.hash = w_other.hash, self.hash return True From fijal at codespeak.net Tue May 20 20:53:17 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 20 May 2008 20:53:17 +0200 (CEST) Subject: [pypy-svn] r55040 - pypy/branch/hybrid-io/pypy/translator/c/test Message-ID: <20080520185317.AE77016854C@codespeak.net> Author: fijal Date: Tue May 20 20:53:16 2008 New Revision: 55040 Modified: pypy/branch/hybrid-io/pypy/translator/c/test/test_newgc.py Log: Wuaaa! Don't skip this test. Modified: pypy/branch/hybrid-io/pypy/translator/c/test/test_newgc.py ============================================================================== --- pypy/branch/hybrid-io/pypy/translator/c/test/test_newgc.py (original) +++ pypy/branch/hybrid-io/pypy/translator/c/test/test_newgc.py Tue May 20 20:53:16 2008 @@ -1007,7 +1007,9 @@ s.append_multiple_char('y', 1000) gc.collect() s.append_multiple_char('y', 1000) - return s.build() + res = s.build() + gc.collect() + return res c_fn = self.getcompiled(fn) res = c_fn() assert res[1000] == 'y' @@ -1021,8 +1023,5 @@ should_be_moving = True GC_CANNOT_MALLOC_NONMOVABLE = False - def test_string_builder_over_allocation(self): - py.test.skip("Segfaulting") - def test_gc_set_max_heap_size(self): py.test.skip("not implemented") From cfbolz at codespeak.net Tue May 20 20:55:37 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 20 May 2008 20:55:37 +0200 (CEST) Subject: [pypy-svn] r55041 - pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk Message-ID: <20080520185537.88F1A16854D@codespeak.net> Author: cfbolz Date: Tue May 20 20:55:36 2008 New Revision: 55041 Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py Log: fix __eq__ and add __hash__ Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py Tue May 20 20:55:36 2008 @@ -125,11 +125,16 @@ return self.value == other.value def __eq__(self, other): + if not isinstance(other, W_SmallInteger): + return False return self.value == other.value def __ne__(self, other): return not self == other + def __hash__(self): + return self.value + class W_Float(W_Object): """Boxed float value.""" @@ -157,11 +162,16 @@ return self.value == other.value def __eq__(self, other): + if not isinstance(other, W_Float): + return False return self.value == other.value def __ne__(self, other): return not self == other + def __hash__(self): + return hash(self.value) + class W_AbstractObjectWithIdentityHash(W_Object): """Object with explicit hash (ie all except small ints and floats).""" From cfbolz at codespeak.net Tue May 20 20:57:36 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 20 May 2008 20:57:36 +0200 (CEST) Subject: [pypy-svn] r55042 - pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk Message-ID: <20080520185736.1D13A16854C@codespeak.net> Author: cfbolz Date: Tue May 20 20:57:34 2008 New Revision: 55042 Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py Log: fix as_context_get_shadow Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py Tue May 20 20:57:34 2008 @@ -335,7 +335,7 @@ if ContextPartShadow.is_block_context(self): return self.as_blockcontext_get_shadow() return self.as_methodcontext_get_shadow() - return self._shadow + self.as_special_get_shadow(ContextPartShadow) def as_methoddict_get_shadow(self): from pypy.lang.smalltalk.shadow import MethodDictionaryShadow From tverwaes at codespeak.net Tue May 20 21:01:26 2008 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Tue, 20 May 2008 21:01:26 +0200 (CEST) Subject: [pypy-svn] r55043 - pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk Message-ID: <20080520190126.C88E1168553@codespeak.net> Author: tverwaes Date: Tue May 20 21:01:24 2008 New Revision: 55043 Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py Log: small bugfix Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py Tue May 20 21:01:24 2008 @@ -306,7 +306,7 @@ if shadow is None: shadow = self.attach_shadow_of_class(TheClass) elif not isinstance(shadow, TheClass): - shadow.sync_w_self() + # TODO Add test for this shadow.invalidate_shadow() shadow = self.attach_shadow_of_class(TheClass) shadow.sync_shadow() @@ -335,7 +335,7 @@ if ContextPartShadow.is_block_context(self): return self.as_blockcontext_get_shadow() return self.as_methodcontext_get_shadow() - self.as_special_get_shadow(ContextPartShadow) + return self.as_special_get_shadow(ContextPartShadow) def as_methoddict_get_shadow(self): from pypy.lang.smalltalk.shadow import MethodDictionaryShadow Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py Tue May 20 21:01:24 2008 @@ -23,6 +23,10 @@ def sync_shadow(self): pass class AbstractCachingShadow(AbstractShadow): + def __init__(self, w_self): + AbstractShadow.__init__(self, w_self) + self.invalid = True + self.invalidate_shadow() def invalidate_shadow(self): """This should get called whenever the base Smalltalk object changes.""" @@ -71,7 +75,7 @@ AbstractCachingShadow.invalidate_shadow(self) self.w_methoddict = None self.w_superclass = None - self.name = None + self.name = "" def getname(self): return "%s class" % (self.name or '?',) From karlb at codespeak.net Wed May 21 10:55:12 2008 From: karlb at codespeak.net (karlb at codespeak.net) Date: Wed, 21 May 2008 10:55:12 +0200 (CEST) Subject: [pypy-svn] r55046 - pypy/dist/pypy/translator/tool Message-ID: <20080521085512.CD0EF1684E2@codespeak.net> Author: karlb Date: Wed May 21 10:55:08 2008 New Revision: 55046 Modified: pypy/dist/pypy/translator/tool/cbuild.py Log: Added missing parameter info to the ExternalCompilationInfo docstring Modified: pypy/dist/pypy/translator/tool/cbuild.py ============================================================================== --- pypy/dist/pypy/translator/tool/cbuild.py (original) +++ pypy/dist/pypy/translator/tool/cbuild.py Wed May 21 10:55:08 2008 @@ -62,6 +62,17 @@ export_symbols: list of names that should be exported by the final binary. + + compile_extra: list of parameters which will be directly passed to + the compiler + + compile_extra: list of parameters which will be directly passed to + the linker + + frameworks: list of Mac OS X frameworks which should passed to the + linker. Use this instead of the 'libraries' parameter if you want to + link to a framework bundle. Not suitable for unix-like .dylib + installations. """ for name in self._ATTRIBUTES: value = locals()[name] From antocuni at codespeak.net Wed May 21 11:29:49 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 21 May 2008 11:29:49 +0200 (CEST) Subject: [pypy-svn] r55047 - pypy/django/tests Message-ID: <20080521092949.3F52D2D8003@codespeak.net> Author: antocuni Date: Wed May 21 11:29:48 2008 New Revision: 55047 Modified: pypy/django/tests/conftest.py Log: run only the docstring we really want to run, not every docstring in the module! Modified: pypy/django/tests/conftest.py ============================================================================== --- pypy/django/tests/conftest.py (original) +++ pypy/django/tests/conftest.py Wed May 21 11:29:48 2008 @@ -3,7 +3,6 @@ import os import sys -# XXX after invalid model tests the testing process bails out! # XXX no django/contrib rootdir = py.path.local(__file__).dirpath() @@ -46,9 +45,11 @@ from django.test import _doctest checker = OutputChecker() runner = DocTestRunner(checker=checker) - finder = _doctest.DocTestFinder() - for test in finder.find(mod): - runner.run(test) + parser = _doctest.DocTestParser() + globs = mod.__dict__.copy() + test = parser.get_doctest(docstring, globs, "foo", "foobar", 0) + import pdb;pdb.set_trace() + runner.run(test) if runner.failures: py.test.fail("doctest %s: %s failed out of %s" %( self.fspath, runner.failures, runner.tries)) From antocuni at codespeak.net Wed May 21 11:30:46 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 21 May 2008 11:30:46 +0200 (CEST) Subject: [pypy-svn] r55048 - pypy/django/tests Message-ID: <20080521093046.4B0442D8003@codespeak.net> Author: antocuni Date: Wed May 21 11:30:45 2008 New Revision: 55048 Modified: pypy/django/tests/conftest.py Log: remove pdb Modified: pypy/django/tests/conftest.py ============================================================================== --- pypy/django/tests/conftest.py (original) +++ pypy/django/tests/conftest.py Wed May 21 11:30:45 2008 @@ -48,7 +48,6 @@ parser = _doctest.DocTestParser() globs = mod.__dict__.copy() test = parser.get_doctest(docstring, globs, "foo", "foobar", 0) - import pdb;pdb.set_trace() runner.run(test) if runner.failures: py.test.fail("doctest %s: %s failed out of %s" %( From karlb at codespeak.net Wed May 21 11:42:10 2008 From: karlb at codespeak.net (karlb at codespeak.net) Date: Wed, 21 May 2008 11:42:10 +0200 (CEST) Subject: [pypy-svn] r55049 - pypy/dist/pypy/rlib/rsdl Message-ID: <20080521094210.6F58E1684E2@codespeak.net> Author: karlb Date: Wed May 21 11:42:09 2008 New Revision: 55049 Modified: pypy/dist/pypy/rlib/rsdl/RSDL_helper.py Log: Added blit complete surface RSDL helper Modified: pypy/dist/pypy/rlib/rsdl/RSDL_helper.py ============================================================================== --- pypy/dist/pypy/rlib/rsdl/RSDL_helper.py (original) +++ pypy/dist/pypy/rlib/rsdl/RSDL_helper.py Wed May 21 11:42:09 2008 @@ -100,3 +100,9 @@ rffi.setintfield(p, 'c_w', w) rffi.setintfield(p, 'c_h', h) return p + +def blit_complete_surface(src, dst, x, y): + dstrect = mallocrect(x, y, rffi.getintfield(src, 'c_w'), rffi.getintfield(src, 'c_w')) + RSDL.BlitSurface(src, lltype.nullptr(RSDL.Rect), dst, dstrect) + lltype.free(dstrect, flavor='raw') + From karlb at codespeak.net Wed May 21 11:42:58 2008 From: karlb at codespeak.net (karlb at codespeak.net) Date: Wed, 21 May 2008 11:42:58 +0200 (CEST) Subject: [pypy-svn] r55050 - pypy/dist/pypy/rlib/rsdl/test Message-ID: <20080521094258.9063A1684E2@codespeak.net> Author: karlb Date: Wed May 21 11:42:57 2008 New Revision: 55050 Added: pypy/dist/pypy/rlib/rsdl/test/test_surface.py Log: Added test for RSDL.SetAlpha Added: pypy/dist/pypy/rlib/rsdl/test/test_surface.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rlib/rsdl/test/test_surface.py Wed May 21 11:42:57 2008 @@ -0,0 +1,48 @@ +import py, sys +from pypy.rlib.rsdl import RSDL, RSDL_helper +from pypy.rlib.rarithmetic import r_uint +from pypy.rpython.lltypesystem import lltype, rffi + +class TestSurface: + + def setup_method(self, meth): + self.large_surface = RSDL.CreateRGBSurface(0, 300, 300, 32, + r_uint(0x000000FF), + r_uint(0x0000FF00), + r_uint(0x00FF0000), + r_uint(0x00000000)) + self.small_surface = RSDL.CreateRGBSurface(0, 50, 50, 32, + r_uint(0x000000FF), + r_uint(0x0000FF00), + r_uint(0x00FF0000), + r_uint(0x00000000)) + fmt = self.small_surface.c_format + color = RSDL.MapRGB(fmt, 255, 0, 0) + RSDL.FillRect(self.small_surface, lltype.nullptr(RSDL.Rect), color) + + def test_simple(self): + pass # only checks that creating the surfaces works + + def test_set_alpha(self): + assert RSDL.SetAlpha(self.small_surface, RSDL.SRCALPHA, 128) == 0 + RSDL_helper.blit_complete_surface( + self.small_surface, + self.large_surface, + 10, 10) + RSDL_helper.blit_complete_surface( + self.small_surface, + self.large_surface, + 20, 20) + for position, color in ( + (( 0, 0), ( 0,0,0)), # no rect + ((10,10), (127,0,0)), # one rect + ((20,20), (191,0,0)) # two overlapping rects + ): + fetched_color = RSDL_helper.get_pixel(self.large_surface, position[0], position[1]) + assert RSDL_helper.get_rgb(fetched_color, self.large_surface.c_format) == color + + def teardown_method(self, meth): + RSDL.FreeSurface(self.small_surface) + RSDL.FreeSurface(self.large_surface) + RSDL.Quit() + From hpk at codespeak.net Wed May 21 11:47:22 2008 From: hpk at codespeak.net (hpk at codespeak.net) Date: Wed, 21 May 2008 11:47:22 +0200 (CEST) Subject: [pypy-svn] r55051 - pypy/django/tests Message-ID: <20080521094722.6613A1684E2@codespeak.net> Author: hpk Date: Wed May 21 11:47:20 2008 New Revision: 55051 Modified: pypy/django/tests/conftest.py Log: (anto,hpk) run the correct doctests Modified: pypy/django/tests/conftest.py ============================================================================== --- pypy/django/tests/conftest.py (original) +++ pypy/django/tests/conftest.py Wed May 21 11:47:20 2008 @@ -23,6 +23,7 @@ class DocTestItem(py.test.collect.Item): def __init__(self, name, mod, docstr): + assert docstr is not None py.test.collect.Item.__init__(self, name) self.docstr = docstr self.mod = mod @@ -47,6 +48,7 @@ runner = DocTestRunner(checker=checker) parser = _doctest.DocTestParser() globs = mod.__dict__.copy() + assert docstring is not None test = parser.get_doctest(docstring, globs, "foo", "foobar", 0) runner.run(test) if runner.failures: @@ -94,10 +96,10 @@ def _find_doctests(self, mod): if hasattr(mod, '__test__'): - return ["__test__[%s]" % x for x in mod.__test__.keys()] + return ["__test__[%s]" % x for x in mod.__test__.keys() + if mod.__test__[x]] if os.path.basename(mod.__file__).startswith("tests") and mod.__doc__: return ['%docmodulestring%'] - #return [)] return [] def _get_mod(self): @@ -121,7 +123,9 @@ mod = self._get_mod() if name.startswith("__test__["): doctestname = name[9:-1] - return DocTestItem(name, mod, mod.__test__[doctestname]) + docstring = mod.__test__[doctestname] + assert docstring is not None + return DocTestItem(name, mod, docstring) elif name.startswith('tests.__test__['): doctestname = name[15:-1] mod = mod.tests @@ -129,7 +133,7 @@ elif name == '%docmodulestring%': return DocTestItem(self.fspath.basename + '.%docstring%', mod, mod.__doc__) elif name == 'tests.%docmodulestring%': - return DocTestItem(self.fspath.basename + '.test.%docstring%', mod, mod.__doc__) + return DocTestItem(self.fspath.basename + '.tests.%docstring%', mod.tests, mod.tests.__doc__) elif name.startswith('tests'): return DjangoUnitTest(name, self) else: @@ -160,8 +164,6 @@ mod = getattr(mod, "tests") else: assert len(names) == 2 - #import pdb - #pdb.set_trace() testcasecls = getattr(mod, names[0]) testcase = testcasecls(names[1]) run_testcase_method(testcase) From antocuni at codespeak.net Wed May 21 11:54:13 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 21 May 2008 11:54:13 +0200 (CEST) Subject: [pypy-svn] r55052 - pypy/django/tests Message-ID: <20080521095413.7A5721684E5@codespeak.net> Author: antocuni Date: Wed May 21 11:54:10 2008 New Revision: 55052 Modified: pypy/django/tests/conftest.py Log: (quite hackish) if __test__ contains a module, use its docstring Modified: pypy/django/tests/conftest.py ============================================================================== --- pypy/django/tests/conftest.py (original) +++ pypy/django/tests/conftest.py Wed May 21 11:54:10 2008 @@ -118,18 +118,24 @@ return mod def join(self, name): + import types if name == '%invalidtestcase%': return DjangoInvalidModelTestCase(name, self) mod = self._get_mod() if name.startswith("__test__["): doctestname = name[9:-1] docstring = mod.__test__[doctestname] + if isinstance(docstring, types.ModuleType): + docstring = docstring.__doc__ assert docstring is not None return DocTestItem(name, mod, docstring) elif name.startswith('tests.__test__['): doctestname = name[15:-1] mod = mod.tests - return DocTestItem(name, mod, mod.__test__[doctestname]) + docstring = mod.__test__[doctestname] + if isinstance(docstring, types.ModuleType): + docstring = docstring.__doc__ + return DocTestItem(name, mod, docstring) elif name == '%docmodulestring%': return DocTestItem(self.fspath.basename + '.%docstring%', mod, mod.__doc__) elif name == 'tests.%docmodulestring%': From arigo at codespeak.net Wed May 21 11:54:37 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 21 May 2008 11:54:37 +0200 (CEST) Subject: [pypy-svn] r55054 - in pypy/dist/pypy/translator/goal: . test2 Message-ID: <20080521095437.304531684EA@codespeak.net> Author: arigo Date: Wed May 21 11:54:35 2008 New Revision: 55054 Modified: pypy/dist/pypy/translator/goal/app_main.py pypy/dist/pypy/translator/goal/test2/test_app_main.py Log: Some more whacking at the command-line option handling logic, trying to slowly converge to CPython's behavior. The latter is desperately lacking any designed -- it is a biologically grown tangle which can set and clear the same internal global flags three times along the way. Modified: pypy/dist/pypy/translator/goal/app_main.py ============================================================================== --- pypy/dist/pypy/translator/goal/app_main.py (original) +++ pypy/dist/pypy/translator/goal/app_main.py Wed May 21 11:54:35 2008 @@ -291,24 +291,38 @@ if hasattr(signal, 'SIGXFSZ'): signal.signal(signal.SIGXFSZ, signal.SIG_IGN) - def is_interactive(): - return go_interactive or os.getenv('PYTHONINSPECT') + 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; + # or + # * PYTHONINSPECT is set and stdin is a tty. + # + return (go_interactive or + (os.getenv('PYTHONINSPECT') and sys.stdin.isatty())) success = True try: if run_command: + # handle the "-c" command cmd = sys.argv.pop(1) def run_it(): exec cmd in mainmodule.__dict__ success = run_toplevel(run_it) elif run_module: + # handle the "-m" command def run_it(): import runpy runpy.run_module(sys.argv[0], None, '__main__', True) success = run_toplevel(run_it) elif run_stdin: - if is_interactive() or sys.stdin.isatty(): + # handle the case where no command/filename/module is specified + # on the command-line. + if go_interactive or sys.stdin.isatty(): + # If stdin is a tty or if "-i" is specified, we print + # a banner and run $PYTHONSTARTUP. print_banner() python_startup = os.getenv('PYTHONSTARTUP') if python_startup: @@ -323,20 +337,25 @@ 'exec') exec co_python_startup in mainmodule.__dict__ run_toplevel(run_it) + # Then we need a prompt. go_interactive = True else: + # If not interactive, just read and execute stdin normally. def run_it(): co_stdin = compile(sys.stdin.read(), '', 'exec') exec co_stdin in mainmodule.__dict__ mainmodule.__file__ = '' success = run_toplevel(run_it) else: + # handle the common case where a filename is specified + # on the command-line. mainmodule.__file__ = sys.argv[0] scriptdir = resolvedirof(sys.argv[0]) sys.path.insert(0, scriptdir) success = run_toplevel(execfile, sys.argv[0], mainmodule.__dict__) - - if is_interactive(): + + # start a prompt if requested + if inspect_requested(): from _pypy_interact import interactive_console success = run_toplevel(interactive_console, mainmodule) except SystemExit, e: Modified: pypy/dist/pypy/translator/goal/test2/test_app_main.py ============================================================================== --- pypy/dist/pypy/translator/goal/test2/test_app_main.py (original) +++ pypy/dist/pypy/translator/goal/test2/test_app_main.py Wed May 21 11:54:35 2008 @@ -6,25 +6,6 @@ import autopath from pypy.tool.udir import udir -DEMO_SCRIPT = """ -print 'hello' -print 'Name:', __name__ -print 'File:', __file__ -import sys -print 'Exec:', sys.executable -print 'Argv:', sys.argv -print 'goodbye' -myvalue = 6*7 -""" - -CRASHING_DEMO_SCRIPT = """ -print 'Hello2' -myvalue2 = 11 -ooups -myvalue2 = 22 -print 'Goodbye2' # should not be reached -""" - banner = sys.version.splitlines()[0] def relpath(path): @@ -43,13 +24,33 @@ app_main = os.path.join(autopath.this_dir, os.pardir, 'app_main.py') app_main = os.path.abspath(app_main) -demo_script_p = udir.join('demo_test_app_main.py') -demo_script_p.write(DEMO_SCRIPT) -demo_script = relpath(demo_script_p) - -crashing_demo_script_p = udir.join('crashing_demo_test_app_main.py') -crashing_demo_script_p.write(CRASHING_DEMO_SCRIPT) -crashing_demo_script = relpath(crashing_demo_script_p) +_counter = 0 +def getscript(source): + global _counter + p = udir.join('demo_test_app_main_%d.py' % (_counter,)) + _counter += 1 + p.write(str(py.code.Source(source))) + return relpath(p) + + +demo_script = getscript(""" + print 'hello' + print 'Name:', __name__ + print 'File:', __file__ + import sys + print 'Exec:', sys.executable + print 'Argv:', sys.argv + print 'goodbye' + myvalue = 6*7 + """) + +crashing_demo_script = getscript(""" + print 'Hello2' + myvalue2 = 11 + ooups + myvalue2 = 22 + print 'Goodbye2' # should not be reached + """) class TestInteraction: @@ -265,22 +266,6 @@ data = os.read(pipe.stdout.fileno(), 1024) assert data.startswith('Python') - def test_options_u_PYTHONINSPECT(self): - if sys.platform == "win32": - skip("close_fds is not supported on Windows platforms") - import subprocess, select, os - python = sys.executable - pipe = subprocess.Popen([python, app_main, "-u"], - stdout=subprocess.PIPE, - stdin=subprocess.PIPE, - stderr=subprocess.STDOUT, - bufsize=0, close_fds=True, - env={'PYTHONINSPECT': '1'}) - iwtd, owtd, ewtd = select.select([pipe.stdout], [], [], 5) - assert iwtd # else we timed out - data = os.read(pipe.stdout.fileno(), 1024) - assert data.startswith('Python') - def test_paste_several_lines_doesnt_mess_prompt(self): py.test.skip("this can only work if readline is enabled") child = self.spawn([]) @@ -291,18 +276,56 @@ child.expect('42') child.expect('>>> ') + def test_pythoninspect(self): + old = os.environ.get('PYTHONINSPECT', '') + try: + os.environ['PYTHONINSPECT'] = '1' + path = getscript(""" + print 6*7 + """) + child = self.spawn([path]) + child.expect('42') + child.expect('>>> ') + finally: + os.environ['PYTHONINSPECT'] = old + + def test_set_pythoninspect(self): + path = getscript(""" + import os + os.environ['PYTHONINSPECT'] = '1' + print 6*7 + """) + child = self.spawn([path]) + child.expect('42') + child.expect('>>> ') + + def test_clear_pythoninspect(self): + py.test.skip("obscure difference with CPython -- do we care?") + old = os.environ.get('PYTHONINSPECT', '') + try: + path = getscript(""" + import os + del os.environ['PYTHONINSPECT'] + """) + child = self.spawn([path]) + xxx # do we expect a prompt or not? CPython gives one + finally: + os.environ['PYTHONINSPECT'] = old + class TestNonInteractive: - def run(self, cmdline): + def run(self, cmdline, senddata='', expect_prompt=False, + expect_banner=False): cmdline = '%s "%s" %s' % (sys.executable, app_main, cmdline) print 'POPEN:', cmdline child_in, child_out_err = os.popen4(cmdline) + child_in.write(senddata) child_in.close() data = child_out_err.read() child_out_err.close() - assert banner not in data # no banner - assert '>>> ' not in data # no prompt + assert (banner in data) == expect_banner # no banner unless expected + assert ('>>> ' in data) == expect_prompt # no prompt unless expected return data def test_script_on_stdin(self): @@ -356,3 +379,26 @@ # concerning drive letters right now. assert ('File: ' + p) in data assert ('Argv: ' + repr([p, 'extra'])) in data + + def test_pythoninspect_doesnt_override_isatty(self): + old = os.environ.get('PYTHONINSPECT', '') + try: + os.environ['PYTHONINSPECT'] = '1' + data = self.run('', senddata='6*7\nprint 2+3\n') + assert data == '5\n' + finally: + os.environ['PYTHONINSPECT'] = old + + def test_i_flag_overrides_isatty(self): + data = self.run('-i', senddata='6*7\nraise SystemExit\n', + expect_prompt=True, expect_banner=True) + assert '42\n' in data + # if a file name is passed, the banner is never printed but + # we get a prompt anyway + cmdline = '-i %s' % getscript(""" + print 'hello world' + """) + data = self.run(cmdline, senddata='6*7\nraise SystemExit\n', + expect_prompt=True, expect_banner=False) + assert 'hello world\n' in data + assert '42\n' in data From hpk at codespeak.net Wed May 21 12:01:15 2008 From: hpk at codespeak.net (hpk at codespeak.net) Date: Wed, 21 May 2008 12:01:15 +0200 (CEST) Subject: [pypy-svn] r55055 - pypy/django/tests Message-ID: <20080521100115.5676D1684E5@codespeak.net> Author: hpk Date: Wed May 21 12:01:13 2008 New Revision: 55055 Modified: pypy/django/tests/conftest.py Log: use the correct filename Modified: pypy/django/tests/conftest.py ============================================================================== --- pypy/django/tests/conftest.py (original) +++ pypy/django/tests/conftest.py Wed May 21 12:01:13 2008 @@ -49,7 +49,7 @@ parser = _doctest.DocTestParser() globs = mod.__dict__.copy() assert docstring is not None - test = parser.get_doctest(docstring, globs, "foo", "foobar", 0) + test = parser.get_doctest(docstring, globs, "foo", mod.__file__, 0) runner.run(test) if runner.failures: py.test.fail("doctest %s: %s failed out of %s" %( From antocuni at codespeak.net Wed May 21 12:20:23 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 21 May 2008 12:20:23 +0200 (CEST) Subject: [pypy-svn] r55056 - pypy/django/tests Message-ID: <20080521102023.569F71684D8@codespeak.net> Author: antocuni Date: Wed May 21 12:20:22 2008 New Revision: 55056 Modified: pypy/django/tests/conftest.py Log: (antocuni, hpk) I hate global state :-/ Modified: pypy/django/tests/conftest.py ============================================================================== --- pypy/django/tests/conftest.py (original) +++ pypy/django/tests/conftest.py Wed May 21 12:20:22 2008 @@ -39,7 +39,10 @@ self.execute(self.mod, self.docstr) finally: destroy_test_db(old_name, 0) - teardown_test_environment() + teardown_test_environment() + # manually clear some global state, as there is not API to do this :-( + from django.core import management + management._commands = None def execute(self, mod, docstring): from django.test.testcases import OutputChecker, DocTestRunner From karlb at codespeak.net Wed May 21 12:24:03 2008 From: karlb at codespeak.net (karlb at codespeak.net) Date: Wed, 21 May 2008 12:24:03 +0200 (CEST) Subject: [pypy-svn] r55057 - in pypy/dist/pypy/rlib/rsdl: . test Message-ID: <20080521102403.CDD88168460@codespeak.net> Author: karlb Date: Wed May 21 12:24:02 2008 New Revision: 55057 Modified: pypy/dist/pypy/rlib/rsdl/RSDL.py pypy/dist/pypy/rlib/rsdl/test/test_surface.py Log: Added support for RSDL.SetColorKey Modified: pypy/dist/pypy/rlib/rsdl/RSDL.py ============================================================================== --- pypy/dist/pypy/rlib/rsdl/RSDL.py (original) +++ pypy/dist/pypy/rlib/rsdl/RSDL.py Wed May 21 12:24:02 2008 @@ -214,6 +214,10 @@ [SurfacePtr, Uint32, Uint8], rffi.INT) +SetColorKey = external('SDL_SetColorKey', + [SurfacePtr, Uint32, Uint32], + rffi.INT) + ShowCursor = external('SDL_ShowCursor', [rffi.INT], rffi.INT) @@ -245,4 +249,4 @@ Init = _Init - \ No newline at end of file + Modified: pypy/dist/pypy/rlib/rsdl/test/test_surface.py ============================================================================== --- pypy/dist/pypy/rlib/rsdl/test/test_surface.py (original) +++ pypy/dist/pypy/rlib/rsdl/test/test_surface.py Wed May 21 12:24:02 2008 @@ -6,43 +6,70 @@ class TestSurface: def setup_method(self, meth): - self.large_surface = RSDL.CreateRGBSurface(0, 300, 300, 32, + self.dst_surf = RSDL.CreateRGBSurface(0, 300, 300, 32, r_uint(0x000000FF), r_uint(0x0000FF00), r_uint(0x00FF0000), r_uint(0x00000000)) - self.small_surface = RSDL.CreateRGBSurface(0, 50, 50, 32, + self.src_surf = RSDL.CreateRGBSurface(0, 50, 50, 32, r_uint(0x000000FF), r_uint(0x0000FF00), r_uint(0x00FF0000), r_uint(0x00000000)) - fmt = self.small_surface.c_format - color = RSDL.MapRGB(fmt, 255, 0, 0) - RSDL.FillRect(self.small_surface, lltype.nullptr(RSDL.Rect), color) + fmt = self.src_surf.c_format + self.black = RSDL.MapRGB(fmt, 0, 0, 0) + self.red = RSDL.MapRGB(fmt, 255, 0, 0) + self.blue = RSDL.MapRGB(fmt, 0, 0, 255) + RSDL.FillRect(self.src_surf, lltype.nullptr(RSDL.Rect), self.red) def test_simple(self): pass # only checks that creating the surfaces works def test_set_alpha(self): - assert RSDL.SetAlpha(self.small_surface, RSDL.SRCALPHA, 128) == 0 + # prepare + assert RSDL.SetAlpha(self.src_surf, RSDL.SRCALPHA, 128) == 0 + + # draw RSDL_helper.blit_complete_surface( - self.small_surface, - self.large_surface, + self.src_surf, + self.dst_surf, 10, 10) RSDL_helper.blit_complete_surface( - self.small_surface, - self.large_surface, + self.src_surf, + self.dst_surf, 20, 20) + + # check for position, color in ( (( 0, 0), ( 0,0,0)), # no rect ((10,10), (127,0,0)), # one rect ((20,20), (191,0,0)) # two overlapping rects ): - fetched_color = RSDL_helper.get_pixel(self.large_surface, position[0], position[1]) - assert RSDL_helper.get_rgb(fetched_color, self.large_surface.c_format) == color + fetched_color = RSDL_helper.get_pixel(self.dst_surf, position[0], position[1]) + assert RSDL_helper.get_rgb(fetched_color, self.dst_surf.c_format) == color + + def test_set_color_key(self): + # prepare + fillrect = RSDL_helper.mallocrect(10, 10, 30, 30) + RSDL.FillRect(self.src_surf, fillrect, self.blue) + lltype.free(fillrect, flavor='raw') + assert RSDL.SetColorKey(self.src_surf, RSDL.SRCCOLORKEY, self.blue) == 0 + + # draw + RSDL_helper.blit_complete_surface(self.src_surf, self.dst_surf, 0, 0) + + # check + for position, color in ( + (( 0, 0), self.red), + ((10,10), self.black), + ((20,20), self.black), + ((40,40), self.red) + ): + fetched_color = RSDL_helper.get_pixel(self.dst_surf, position[0], position[1]) + assert fetched_color == color def teardown_method(self, meth): - RSDL.FreeSurface(self.small_surface) - RSDL.FreeSurface(self.large_surface) + RSDL.FreeSurface(self.src_surf) + RSDL.FreeSurface(self.dst_surf) RSDL.Quit() From arigo at codespeak.net Wed May 21 12:45:21 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 21 May 2008 12:45:21 +0200 (CEST) Subject: [pypy-svn] r55058 - pypy/dist/pypy/doc Message-ID: <20080521104521.D7CF8168567@codespeak.net> Author: arigo Date: Wed May 21 12:45:21 2008 New Revision: 55058 Modified: pypy/dist/pypy/doc/getting-started.txt Log: Update the section about translating a pypy-c. Modified: pypy/dist/pypy/doc/getting-started.txt ============================================================================== --- pypy/dist/pypy/doc/getting-started.txt (original) +++ pypy/dist/pypy/doc/getting-started.txt Wed May 21 12:45:21 2008 @@ -568,69 +568,54 @@ .. _`windows document`: windows.html -Not for the faint of heart nor the owner of a very old machine: you can +You can translate the PyPy's whole of Python interpreter to low level C code. This is the largest and -ultimate example of source that our translation toolchain can process:: +ultimate example of source that our translation toolchain can process. +If you don't need threads, the most standard variant nowadays is:: cd pypy/translator/goal - python translate.py --run targetpypystandalone.py + python translate.py --gc=hybrid targetpypystandalone.py --allworkingmodules --faassen -By default the translation process will try to use the -`Boehm-Demers-Weiser garbage collector`_ for the translated interpreter. Use -``--gc=generation`` to use our own exact generational implementation which -is now faster and doesn't have external dependencies. Otherwise, be -sure to install Boehm before starting the translation (e.g. by running -``apt-get install libgc-dev`` on Debian or Ubuntu). - -This whole process will take some time and quite a lot of memory (although it -might just work on a machine with 512MB of RAM). If the translation is -finished running and after you closed the graph you will be greeted -(because of ``--run`` option) by the friendly prompt of a PyPy -executable that is not running on top of CPython any more:: - - [translation:info] created: ./pypy-c - [translation:info] Running compiled c source... - debug: entry point starting - debug: argv -> ./pypy-c - debug: importing code - debug: calling code.interact() - Python 2.4.1 (pypy 0.7.1 build 18929) on linux2 - Type "help", "copyright", "credits" or "license" for more information. - (InteractiveConsole) - >>>> 1 + 1 - 2 - >>>> +This whole process will take some time and quite a lot of memory (around +1GB). It creates an executable ``pypy-c`` in the current directory. +The ``--gc=hybrid`` option means that the ``pypy-c`` will use our own +exact generational garbage collector implementation, whose performance +is rather good nowadays. The ``--faassen`` option enables all the +worthwhile performance optimizations, but slows down the translation +itself. On Linux 32-bit Intel machines you can also add +``--gcrootfinder=asmgcc`` after ``--gc=hybrid`` for extra speed (and +extra translation time). + +At the moment, threads only work with the `Boehm-Demers-Weiser garbage +collector`_. So to enable them, you need instead:: + + cd pypy/translator/goal + python translate.py --thread targetpypystandalone.py --allworkingmodules --faassen + +Be sure to install Boehm before starting the translation (e.g. by running +``apt-get install libgc-dev`` on Debian or Ubuntu). Translating with Boehm +is a bit faster and less memory-hungry than translating with our own GCs. -With the default options, you can find the produced executable under the +In any case, as described above, you can find the produced executable under the name ``pypy-c``. Type ``pypy-c --help`` to see the options it supports -- mainly the same basic options as CPython. In addition, ``pypy-c --info`` prints the translation options that where used to produce this particular -executable. This executable contains a lot of things that are hard-coded -for your particular system, so it's not really meant to -be installed or redistributed at the moment. - -If you exit the interpreter you get a pygame window with all the flow graphs -plus a pdb prompt. Moving around in the resulting flow graph is difficult -because of the sheer size of the result. For this reason, the debugger prompt -you get at the end has been enhanced with commands to facilitate locating -functions and classes. Type ``help graphs`` for a list of the new commands. -Help is also available on each of these new commands. +executable. This executable can be moved around or copied on other machines; +see Installation_ below. -The ``translate.py`` script itself takes a number of options controlling +The ``translate.py`` script takes a very large number of options controlling what to translate and how. See ``translate.py -h``. Some of the more interesting options are: - * ``--text``: don't show the flow graph after the translation is - done. This is useful if you don't have pygame installed. - * ``--stackless``: this produces a pypy-c that includes features inspired by `Stackless Python `__. - * ``--gc=boehm|ref|marknsweep|semispace|generation``: choose between using + * ``--gc=boehm|ref|marknsweep|semispace|generation|hybrid``: + choose between using the `Boehm-Demers-Weiser garbage collector`_, our reference counting implementation or three of own collector implementations - (as we have seen Boehm's collector is the default). + (Boehm's collector is the default). Find a more detailed description of the various options in our `configuration sections`_. @@ -739,6 +724,34 @@ loaded when accessing .NET namespaces as they were Python modules, as IronPython does. +Installation +++++++++++++ + +A prebuilt ``pypy-c`` can be installed in a standard location like +``/usr/local/bin``, although some details of this process are still in +flux. It can also be copied to other machines as long as their system +is "similar enough": some details of the system on which the translation +occurred might be hard-coded in the executable. + +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.4.1``, ``lib-python/modified-2.4.1`` and +``pypy/lib``. 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.4.1`` and ``PREFIX/lib-python/modified.2.4.1`` and +``PREFIX/pypy/lib`` can all be found. The prefixes that are tried are:: + + . + ./share/pypy-1.0 + .. + ../share/pypy-1.0 + ../.. + ../../share/pypy-1.0 + ../../.. + etc. + + .. _`start reading sources`: Where to start reading the sources From antocuni at codespeak.net Wed May 21 13:03:53 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 21 May 2008 13:03:53 +0200 (CEST) Subject: [pypy-svn] r55059 - in pypy/django/tests: . regressiontests/bug639 Message-ID: <20080521110353.2170316854C@codespeak.net> Author: antocuni Date: Wed May 21 13:03:51 2008 New Revision: 55059 Modified: pypy/django/tests/conftest.py pypy/django/tests/regressiontests/bug639/tests.py Log: th Modified: pypy/django/tests/conftest.py ============================================================================== --- pypy/django/tests/conftest.py (original) +++ pypy/django/tests/conftest.py Wed May 21 13:03:51 2008 @@ -102,7 +102,11 @@ return ["__test__[%s]" % x for x in mod.__test__.keys() if mod.__test__[x]] if os.path.basename(mod.__file__).startswith("tests") and mod.__doc__: - return ['%docmodulestring%'] + from django.test import _doctest + parser = _doctest.DocTestParser() + examples = parser.get_examples(mod.__doc__) + if examples: + return ['%docmodulestring%'] return [] def _get_mod(self): Modified: pypy/django/tests/regressiontests/bug639/tests.py ============================================================================== --- pypy/django/tests/regressiontests/bug639/tests.py (original) +++ pypy/django/tests/regressiontests/bug639/tests.py Wed May 21 13:03:51 2008 @@ -39,4 +39,4 @@ Make sure to delete the "uploaded" file to avoid clogging /tmp. """ p = Photo.objects.get() - os.unlink(p.get_image_filename()) \ No newline at end of file + os.unlink(p.get_image_filename()) From arigo at codespeak.net Wed May 21 13:09:38 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 21 May 2008 13:09:38 +0200 (CEST) Subject: [pypy-svn] r55060 - pypy/dist/pypy/doc Message-ID: <20080521110938.CBDF916854B@codespeak.net> Author: arigo Date: Wed May 21 13:09:37 2008 New Revision: 55060 Modified: pypy/dist/pypy/doc/getting-started.txt Log: More updates. Modified: pypy/dist/pypy/doc/getting-started.txt ============================================================================== --- pypy/dist/pypy/doc/getting-started.txt (original) +++ pypy/dist/pypy/doc/getting-started.txt Wed May 21 13:09:37 2008 @@ -11,10 +11,10 @@ ============== PyPy is an implementation of the Python_ programming language written in -Python itself, flexible and easy to experiment with. Our long-term goals are -to target a large variety of platforms, small and large, by providing a +Python itself, flexible and easy to experiment with. +We target a large variety of platforms, small and large, by providing a compiler toolsuite that can produce custom Python versions. Platform, memory -and threading models are to become aspects of the translation process - as +and threading models are aspects of the translation process - as opposed to encoding low level details into the language implementation itself. Eventually, dynamic optimization techniques - implemented as another translation aspect - should become robust against language changes. `more...`_ @@ -30,6 +30,9 @@ Downloading & running the PyPy 1.0 release -------------------------------------------- +*Note: the 1.0 release is out of date. We strongly recommend that you +use the latest stable version* (which you can `get via Subversion`_). + Download one of the following release files: *pypy-1.0* @@ -74,6 +77,7 @@ .. _`pypy-1.0.0-win32.zip`: http://codespeak.net/download/pypy/pypy-1.0.0-win32.zip .. _`latest stable version via subversion`: +.. _`get via Subversion`: Svn-check out & run the latest PyPy as a two-liner -------------------------------------------------- @@ -150,11 +154,14 @@ Interesting Starting Points in PyPy =================================== -The following assumes that you have successfully downloaded and extracted the -PyPy release or have checked out PyPy using svn. It assumes that you are in -the top level directory of the PyPy source tree, e.g. pypy-x.x (if you -got a release) or pypy-dist (if you checked out the most recent version using -subversion). +*The following assumes that you have successfully checked out PyPy using +svn. Some of the following examples don't work in the release 1.0.* + +To get started with PyPy, you can either play with `the py.py +interpreter`_ and the `special PyPy features`_, or directly proceed to +`translating the PyPy Python interpreter`_. This allows you to try out +real Python applications in a fast version of PyPy, compiled via C, +LLVM, .NET or Java, with or without special features included. Main entry point ------------------------------------------ @@ -182,7 +189,7 @@ The parameter is the number of loops to run through the test. The default is 50000, which is far too many to run in a non-translated PyPy version (i.e. when PyPy's interpreter itself is being interpreted -by CPython). +by CPython). py.py options +++++++++++++ @@ -364,12 +371,9 @@ * Download and install Pygame_. - * Download and install `Dot Graphviz`_. - -or: - - * Have an internet connection. The flowgraph viewer connects to - codespeak.net and lets it convert the flowgraph by a graphviz server. + * Download and install `Dot Graphviz`_ (optional if you have an internet + connection: the flowgraph viewer then connects to + codespeak.net and lets it convert the flowgraph by a graphviz server). To start the interactive translator shell do:: From tverwaes at codespeak.net Wed May 21 14:55:57 2008 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Wed, 21 May 2008 14:55:57 +0200 (CEST) Subject: [pypy-svn] r55062 - in pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk: . test Message-ID: <20080521125557.CECDB168064@codespeak.net> Author: tverwaes Date: Wed May 21 14:55:54 2008 New Revision: 55062 Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_shadow.py Log: fixing shadow replacing Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py Wed May 21 14:55:54 2008 @@ -306,8 +306,7 @@ if shadow is None: shadow = self.attach_shadow_of_class(TheClass) elif not isinstance(shadow, TheClass): - # TODO Add test for this - shadow.invalidate_shadow() + shadow.detach_shadow() shadow = self.attach_shadow_of_class(TheClass) shadow.sync_shadow() return shadow Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py Wed May 21 14:55:54 2008 @@ -27,6 +27,10 @@ AbstractShadow.__init__(self, w_self) self.invalid = True self.invalidate_shadow() + + def detach_shadow(self): + self.invalidate_shadow() + def invalidate_shadow(self): """This should get called whenever the base Smalltalk object changes.""" Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_shadow.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_shadow.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_shadow.py Wed May 21 14:55:54 2008 @@ -165,3 +165,17 @@ s_object.detach_shadow() assert w_object._vars == old_vars assert w_object._vars is not old_vars + +def test_replace_to_bc(): + w_object = blockcontext(pc=13) + old_vars = w_object._vars + s_object = w_object.as_blockcontext_get_shadow() + s_object.detach_shadow() + s_classshadow = shadow.ClassShadow(w_object) + w_object._shadow = s_classshadow + s_classshadow.invalid = False + s_newobject = w_object.as_blockcontext_get_shadow() + assert s_classshadow.invalid + assert ([s_newobject.fetch(i) for i in range(s_newobject.size())] == + [s_object.fetch(i) for i in range(s_newobject.size())]) + assert w_object._shadow is s_newobject From karlb at codespeak.net Wed May 21 15:30:23 2008 From: karlb at codespeak.net (karlb at codespeak.net) Date: Wed, 21 May 2008 15:30:23 +0200 (CEST) Subject: [pypy-svn] r55063 - in pypy/dist/pypy/rlib/rsdl: . test Message-ID: <20080521133023.1439E16844F@codespeak.net> Author: karlb Date: Wed May 21 15:30:21 2008 New Revision: 55063 Added: pypy/dist/pypy/rlib/rsdl/RMix.py pypy/dist/pypy/rlib/rsdl/test/test_sdl_mixer.py Modified: pypy/dist/pypy/rlib/rsdl/RSDL.py Log: Adding SDL_mixer support to RSDL Added: pypy/dist/pypy/rlib/rsdl/RMix.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rlib/rsdl/RMix.py Wed May 21 15:30:21 2008 @@ -0,0 +1,17 @@ +from pypy.rpython.lltypesystem import lltype, rffi +from pypy.rpython.tool import rffi_platform as platform +from pypy.translator.tool.cbuild import ExternalCompilationInfo +from pypy.rlib.rsdl import RSDL + +eci = ExternalCompilationInfo( + includes=['SDL_mixer.h'], + libraries=['SDL_mixer'], + ) +eci = eci.merge(RSDL.eci) + +def external(name, args, result): + return rffi.llexternal(name, args, result, compilation_info=eci) + +OpenAudio = external('Mix_OpenAudio', + [rffi.INT, RSDL.Uint16, rffi.INT, rffi.INT], + rffi.INT) Modified: pypy/dist/pypy/rlib/rsdl/RSDL.py ============================================================================== --- pypy/dist/pypy/rlib/rsdl/RSDL.py (original) +++ pypy/dist/pypy/rlib/rsdl/RSDL.py Wed May 21 15:30:21 2008 @@ -234,6 +234,10 @@ [rffi.INT], rffi.CCHARP) +GetError = external('SDL_GetError', + [], + rffi.CCHARP) + # ------------------------------------------------------------------------------ Added: pypy/dist/pypy/rlib/rsdl/test/test_sdl_mixer.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rlib/rsdl/test/test_sdl_mixer.py Wed May 21 15:30:21 2008 @@ -0,0 +1,9 @@ +import py, os +import autopath +from pypy.rlib.rsdl import RSDL, RMix, RSDL_helper +from pypy.rpython.lltypesystem import lltype, rffi + +def test_open_mixer(): + if RMix.OpenAudio(22050, RSDL.AUDIO_S16LSB, 2, 1024) != 0: + error = rffi.charp2str(RSDL.GetError()) + raise Exception(error) From arigo at codespeak.net Wed May 21 15:40:20 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 21 May 2008 15:40:20 +0200 (CEST) Subject: [pypy-svn] r55064 - in pypy/dist/pypy/rpython: lltypesystem lltypesystem/test memory/gc Message-ID: <20080521134020.5DA881684D6@codespeak.net> Author: arigo Date: Wed May 21 15:40:19 2008 New Revision: 55064 Modified: pypy/dist/pypy/rpython/lltypesystem/rffi.py pypy/dist/pypy/rpython/lltypesystem/test/test_rffi.py pypy/dist/pypy/rpython/memory/gc/generation.py Log: Test and fix for a missing annenforceargs. That's the proper fix for the NonConstant hack. Modified: pypy/dist/pypy/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rffi.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rffi.py Wed May 21 15:40:19 2008 @@ -456,6 +456,7 @@ array[i] = s[i] array[len(s)] = '\x00' return array +str2charp._annenforceargs_ = [str] def free_charp(cp): lltype.free(cp, flavor='raw') Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_rffi.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/test/test_rffi.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/test/test_rffi.py Wed May 21 15:40:19 2008 @@ -674,3 +674,19 @@ def test_hashdefine(self): py.test.skip("Macros cannot be called as llexternals by design, rffi does not have any special support for them") + + +def test_enforced_args(): + from pypy.annotation.model import s_None + from pypy.rpython.annlowlevel import MixLevelHelperAnnotator + from pypy.translator.interactive import Translation + def f1(): + str2charp("hello") + def f2(): + str2charp("world") + t = Translation(f1, []) + t.rtype() + mixann = MixLevelHelperAnnotator(t.context.rtyper) + mixann.getgraph(f2, [], s_None) + mixann.finish() + Modified: pypy/dist/pypy/rpython/memory/gc/generation.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gc/generation.py (original) +++ pypy/dist/pypy/rpython/memory/gc/generation.py Wed May 21 15:40:19 2008 @@ -8,7 +8,6 @@ from pypy.rlib.objectmodel import free_non_gc_object from pypy.rlib.debug import ll_assert from pypy.rpython.lltypesystem.lloperation import llop -from pypy.rlib.nonconst import NonConstant # The following flag is never set on young objects, i.e. the ones living # in the nursery. It is initially set on all prebuilt and old objects, @@ -653,7 +652,7 @@ l2cache_p[0] = rffi.cast(rffi.LONGLONG, 0) len_p[0] = rffi.cast(rffi.SIZE_T, size) # XXX a hack for llhelper not being robust-enough - result = sysctlbyname(NonConstant("hw.l2cachesize"), + result = sysctlbyname("hw.l2cachesize", rffi.cast(rffi.VOIDP, l2cache_p), len_p, lltype.nullptr(rffi.VOIDP.TO), From arigo at codespeak.net Wed May 21 16:04:59 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 21 May 2008 16:04:59 +0200 (CEST) Subject: [pypy-svn] r55065 - in pypy/dist/pypy: config interpreter objspace/std rlib rlib/test rpython rpython/lltypesystem rpython/lltypesystem/test rpython/memory rpython/memory/gc rpython/memory/gctransform rpython/memory/test rpython/module rpython/module/test rpython/ootypesystem rpython/test translator translator/backendopt translator/backendopt/test translator/c translator/c/test translator/goal translator/llvm Message-ID: <20080521140459.DEE1E16842F@codespeak.net> Author: arigo Date: Wed May 21 16:04:51 2008 New Revision: 55065 Added: pypy/dist/pypy/rpython/lltypesystem/rbuilder.py - copied unchanged from r54649, pypy/branch/hybrid-io/pypy/rpython/lltypesystem/rbuilder.py pypy/dist/pypy/rpython/ootypesystem/rbuilder.py - copied unchanged from r54649, pypy/branch/hybrid-io/pypy/rpython/ootypesystem/rbuilder.py pypy/dist/pypy/rpython/rbuilder.py - copied unchanged from r54649, pypy/branch/hybrid-io/pypy/rpython/rbuilder.py pypy/dist/pypy/rpython/test/test_rbuilder.py - copied unchanged from r54649, pypy/branch/hybrid-io/pypy/rpython/test/test_rbuilder.py pypy/dist/pypy/translator/goal/targetreadlines.py - copied unchanged from r54649, pypy/branch/hybrid-io/pypy/translator/goal/targetreadlines.py pypy/dist/pypy/translator/goal/targetsimpleread.py - copied unchanged from r54649, pypy/branch/hybrid-io/pypy/translator/goal/targetsimpleread.py pypy/dist/pypy/translator/goal/targetsimplewrite.py - copied unchanged from r54649, pypy/branch/hybrid-io/pypy/translator/goal/targetsimplewrite.py Removed: pypy/dist/pypy/translator/backendopt/coalloc.py pypy/dist/pypy/translator/backendopt/test/test_coalloc.py Modified: pypy/dist/pypy/config/translationoption.py pypy/dist/pypy/interpreter/pyframe.py pypy/dist/pypy/interpreter/pyopcode.py pypy/dist/pypy/objspace/std/formatting.py pypy/dist/pypy/objspace/std/stringobject.py pypy/dist/pypy/rlib/rgc.py pypy/dist/pypy/rlib/rsocket.py pypy/dist/pypy/rlib/rstring.py pypy/dist/pypy/rlib/rzlib.py pypy/dist/pypy/rlib/streamio.py pypy/dist/pypy/rlib/test/test_rgc.py pypy/dist/pypy/rlib/test/test_rsocket.py pypy/dist/pypy/rlib/test/test_rstring.py pypy/dist/pypy/rpython/annlowlevel.py pypy/dist/pypy/rpython/llinterp.py pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py pypy/dist/pypy/rpython/lltypesystem/ll_str.py pypy/dist/pypy/rpython/lltypesystem/llheap.py pypy/dist/pypy/rpython/lltypesystem/llmemory.py pypy/dist/pypy/rpython/lltypesystem/lloperation.py pypy/dist/pypy/rpython/lltypesystem/lltype.py pypy/dist/pypy/rpython/lltypesystem/rffi.py pypy/dist/pypy/rpython/lltypesystem/rstr.py pypy/dist/pypy/rpython/lltypesystem/test/test_ll2ctypes.py pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py pypy/dist/pypy/rpython/lltypesystem/test/test_lltype.py pypy/dist/pypy/rpython/lltypesystem/test/test_rffi.py pypy/dist/pypy/rpython/memory/gc/base.py pypy/dist/pypy/rpython/memory/gc/generation.py pypy/dist/pypy/rpython/memory/gctransform/boehm.py pypy/dist/pypy/rpython/memory/gctransform/framework.py pypy/dist/pypy/rpython/memory/gctransform/transform.py pypy/dist/pypy/rpython/memory/gcwrapper.py pypy/dist/pypy/rpython/memory/test/test_gc.py pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py pypy/dist/pypy/rpython/module/ll_os.py pypy/dist/pypy/rpython/module/test/test_posix.py pypy/dist/pypy/rpython/rpbc.py pypy/dist/pypy/rpython/test/test_annlowlevel.py pypy/dist/pypy/rpython/test/test_rbuiltin.py pypy/dist/pypy/rpython/test/test_rlist.py pypy/dist/pypy/rpython/test/test_runicode.py pypy/dist/pypy/rpython/typesystem.py pypy/dist/pypy/translator/backendopt/all.py pypy/dist/pypy/translator/c/funcgen.py pypy/dist/pypy/translator/c/test/test_boehm.py pypy/dist/pypy/translator/c/test/test_lltyped.py pypy/dist/pypy/translator/c/test/test_newgc.py pypy/dist/pypy/translator/exceptiontransform.py pypy/dist/pypy/translator/llvm/opwriter.py Log: (fijal, arigo, docgok) Merge the io-improvements branch (by repeating the merge that was done at the beginning of the hybrid-io branch). svn merge -r54648:54649 svn+ssh://codespeak.net/svn/pypy/branch/hybrid-io . This branch approaches problem of io (and string operations) bottlenecks by introducing few gc primitives that can express better certain situations. * Implement rgc.can_move(ptr) primitive and rgc.malloc_nonmovable which respectively tells whether pointer can move and tries to allocate area that will never move. Useful for passing into C-level functions. * Use this interface to speedup os.read, os.write, rsocket.send/recv and rzlib * Various small performance improvements, including streamio readline and rstr using raw_memcopy instead of copying by hand * Implement resizable_buffer interface, which exposes three functions: rgc.resizable_buffer_of_shape, rgc.resize_buffer and rgc.finish_building_buffer * Implement rlib.rstring.StringBuilder and UnicodeBuilder, which uses resizable_buffer interface for in-place string building. * Use StringBuilder/UnicodeBuilder for modulo operation on str/unicode and for repr(str) * Implement GC_REALLOC for boehm, using rffi (which is way nicer :) * Introduce new operation FORCE_CAST, for casting between different types on top of llinterp * Remove coalloc, it speeded up things by accident Modified: pypy/dist/pypy/config/translationoption.py ============================================================================== --- pypy/dist/pypy/config/translationoption.py (original) +++ pypy/dist/pypy/config/translationoption.py Wed May 21 16:04:51 2008 @@ -176,9 +176,6 @@ BoolOption("heap2stack", "Escape analysis and stack allocation", default=False, requires=[("translation.stackless", False)]), - BoolOption("coalloc", "Try to replace mallocs by coallocation", - default=False, - suggests=[("translation.gc", "generation")]), # control profile based inlining StrOption("profile_based_inline", "Use call count profiling to drive inlining" Modified: pypy/dist/pypy/interpreter/pyframe.py ============================================================================== --- pypy/dist/pypy/interpreter/pyframe.py (original) +++ pypy/dist/pypy/interpreter/pyframe.py Wed May 21 16:04:51 2008 @@ -9,8 +9,6 @@ import opcode from pypy.rlib.objectmodel import we_are_translated, instantiate from pypy.rlib.jit import we_are_jitted, hint -from pypy.rlib import rstack # for resume points - # Define some opcodes used g = globals() @@ -102,6 +100,7 @@ def execute_frame(self): """Execute this frame. Main entry point to the interpreter.""" + from pypy.rlib import rstack executioncontext = self.space.getexecutioncontext() executioncontext.enter(self) try: Modified: pypy/dist/pypy/interpreter/pyopcode.py ============================================================================== --- pypy/dist/pypy/interpreter/pyopcode.py (original) +++ pypy/dist/pypy/interpreter/pyopcode.py Wed May 21 16:04:51 2008 @@ -18,7 +18,6 @@ from pypy.tool.stdlib_opcode import opcodedesc, HAVE_ARGUMENT from pypy.tool.stdlib_opcode import unrolling_opcode_descs from pypy.tool.stdlib_opcode import opcode_method_names -from pypy.rlib import rstack # for resume points from pypy.rlib.unroll import unrolling_iterable def unaryoperation(operationname): @@ -70,6 +69,8 @@ def dispatch(self, pycode, next_instr, ec): # For the sequel, force 'next_instr' to be unsigned for performance + from pypy.rlib import rstack # for resume points + next_instr = r_uint(next_instr) co_code = pycode.co_code @@ -82,6 +83,8 @@ return self.popvalue() def handle_bytecode(self, co_code, next_instr, ec): + from pypy.rlib import rstack # for resume points + try: next_instr = self.dispatch_bytecode(co_code, next_instr, ec) rstack.resume_point("handle_bytecode", self, co_code, ec, @@ -203,6 +206,8 @@ return next_instr if we_are_translated(): + from pypy.rlib import rstack # for resume points + for opdesc in unrolling_opcode_descs: # static checks to skip this whole case if necessary if not opdesc.is_enabled(space): @@ -850,6 +855,8 @@ f.space.w_None) def call_function(f, oparg, w_star=None, w_starstar=None): + from pypy.rlib import rstack # for resume points + n_arguments = oparg & 0xff n_keywords = (oparg>>8) & 0xff keywords = None @@ -863,6 +870,8 @@ f.pushvalue(w_result) def CALL_FUNCTION(f, oparg, *ignored): + from pypy.rlib import rstack # for resume points + # XXX start of hack for performance if (oparg >> 8) & 0xff == 0: # Only positional arguments Modified: pypy/dist/pypy/objspace/std/formatting.py ============================================================================== --- pypy/dist/pypy/objspace/std/formatting.py (original) +++ pypy/dist/pypy/objspace/std/formatting.py Wed May 21 16:04:51 2008 @@ -5,8 +5,7 @@ from pypy.rlib.rarithmetic import ovfcheck, formatd_overflow, isnan, isinf from pypy.interpreter.error import OperationError from pypy.tool.sourcetools import func_with_new_name -from pypy.rlib.debug import check_annotation -from pypy.rlib.objectmodel import newlist +from pypy.rlib.rstring import StringBuilder, UnicodeBuilder class BaseStringFormatter(object): def __init__(self, space, values_w, w_valuedict): @@ -257,7 +256,10 @@ return result def format(self): - result = newlist(sizehint=100) # list of characters or unichars + if do_unicode: + result = UnicodeBuilder() + else: + result = StringBuilder() self.result = result while True: # fast path: consume as many characters as possible @@ -268,9 +270,9 @@ break i += 1 else: - result += const(fmt[i0:]) - break # end of 'fmt' string - result += const(fmt[i0:i]) + result.append_slice(fmt, i0, len(fmt)) + break # end of 'fmt' string + result.append_slice(fmt, i0, i) self.fmtpos = i + 1 # interpret the next formatter @@ -296,7 +298,7 @@ self.unknown_fmtchar() self.checkconsumed() - return result + return result.build() def unknown_fmtchar(self): space = self.space @@ -317,22 +319,28 @@ def std_wp(self, r): length = len(r) + if do_unicode and isinstance(r, str): + # convert string to unicode explicitely here + r = unicode(r) prec = self.prec if prec == -1 and self.width == 0: # fast path - self.result += const(r) + self.result.append(const(r)) return if prec >= 0 and prec < length: length = prec # ignore the end of the string if too long result = self.result padding = self.width - length + if padding < 0: + padding = 0 + assert padding >= 0 if not self.f_ljust and padding > 0: - result += const(' ') * padding + result.append_multiple_char(const(' '), padding) # add any padding at the left of 'r' padding = 0 - result += const(r[:length]) # add 'r' itself + result.append_slice(r, 0, length) # add 'r' itself if padding > 0: - result += const(' ') * padding + result.append_multiple_char(const(' '), padding) # add any remaining padding at the right std_wp._annspecialcase_ = 'specialize:argtype(1)' @@ -351,6 +359,8 @@ # by pushing the pad character into self.result result = self.result padding = self.width - len(r) - len(prefix) + if padding <= 0: + padding = 0 if self.f_ljust: padnumber = '<' @@ -359,16 +369,20 @@ else: padnumber = '>' + assert padding >= 0 if padnumber == '>': - result += const(' ') * padding # pad with spaces on the left + result.append_multiple_char(const(' '), padding) + # pad with spaces on the left if sign: - result += const(r[0]) # the sign - result += const(prefix) # the prefix + result.append(const(r[0])) # the sign + result.append(const(prefix)) # the prefix if padnumber == '0': - result += const('0') * padding # pad with zeroes - result += const(r[int(sign):]) # the rest of the number + result.append_multiple_char(const('0'), padding) + # pad with zeroes + result.append_slice(const(r), int(sign), len(r)) + # the rest of the number if padnumber == '<': # spaces on the right - result += const(' ') * padding + result.append_multiple_char(const(' '), padding) def fmt_s(self, w_value): space = self.space @@ -455,14 +469,12 @@ # fall through to the unicode case fmt = unicode(fmt) else: - check_annotation(result, is_list_of_chars_or_unichars) - return space.wrap(''.join(result)) + return space.wrap(result) else: fmt = space.unicode_w(w_fmt) formatter = UnicodeFormatter(space, fmt, values_w, w_valuedict) result = formatter.format() - check_annotation(result, is_list_of_chars_or_unichars) - return space.wrap(u''.join(result)) + return space.wrap(result) def mod_format(space, w_format, w_values, do_unicode=False): if space.is_true(space.isinstance(w_values, space.w_tuple)): Modified: pypy/dist/pypy/objspace/std/stringobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/stringobject.py (original) +++ pypy/dist/pypy/objspace/std/stringobject.py Wed May 21 16:04:51 2008 @@ -10,6 +10,7 @@ from pypy.objspace.std.listobject import W_ListObject from pypy.objspace.std.noneobject import W_NoneObject from pypy.objspace.std.tupleobject import W_TupleObject +from pypy.rlib.rstring import StringBuilder from pypy.objspace.std.stringtype import sliced, joined, wrapstr, wrapchar, \ stringendswith, stringstartswith, joined2 @@ -860,17 +861,17 @@ def repr__String(space, w_str): s = w_str._value - i = 0 - buf = [' '] * (len(s) * 4 + 2) # safely overallocate + buf = StringBuilder(len(s) + 10) quote = "'" if quote in s and '"' not in s: quote = '"' - buf[i] = quote + buf.append(quote) + startslice = 0 - for c in s: - i += 1 + for i in range(len(s)): + c = s[i] use_bs_char = False # character quoted by backspace if c == '\\' or c == quote: @@ -887,25 +888,26 @@ use_bs_char = True elif not '\x20' <= c < '\x7f': n = ord(c) - buf[i] = '\\' - i += 1 - buf[i] = 'x' - i += 1 - buf[i] = "0123456789abcdef"[n>>4] - i += 1 - buf[i] = "0123456789abcdef"[n&0xF] - else: - buf[i] = c + if i != startslice: + buf.append_slice(s, startslice, i) + startslice = i + 1 + buf.append('\\x') + buf.append("0123456789abcdef"[n>>4]) + buf.append("0123456789abcdef"[n&0xF]) if use_bs_char: - buf[i] = '\\' - i += 1 - buf[i] = bs_char + if i != startslice: + buf.append_slice(s, startslice, i) + startslice = i + 1 + buf.append('\\') + buf.append(bs_char) + + if len(s) != startslice: + buf.append_slice(s, startslice, len(s)) - i += 1 - buf[i] = quote + buf.append(quote) - return space.wrap("".join(buf[:i+1])) # buffer was overallocated, so slice + return space.wrap(buf.build()) def str_translate__String_ANY_ANY(space, w_string, w_table, w_deletechars=''): Modified: pypy/dist/pypy/rlib/rgc.py ============================================================================== --- pypy/dist/pypy/rlib/rgc.py (original) +++ pypy/dist/pypy/rlib/rgc.py Wed May 21 16:04:51 2008 @@ -185,3 +185,139 @@ opname = 'gc__' + self.instance.__name__ hop.exception_cannot_occur() return hop.genop(opname, [], resulttype=hop.r_result) + +def can_move(p): + return True + +class CanMoveEntry(ExtRegistryEntry): + _about_ = can_move + + def compute_result_annotation(self, s_p): + from pypy.annotation import model as annmodel + return annmodel.SomeBool() + + def specialize_call(self, hop): + from pypy.rpython.lltypesystem import lltype + hop.exception_cannot_occur() + return hop.genop('gc_can_move', hop.args_v, resulttype=hop.r_result) + +def malloc_nonmovable(TP, n=None): + """ Allocate a non-moving buffer or return nullptr. + When running directly, will pretend that gc is always + moving (might be configurable in a future) + """ + from pypy.rpython.lltypesystem import lltype + return lltype.nullptr(TP) + +class MallocNonMovingEntry(ExtRegistryEntry): + _about_ = malloc_nonmovable + + def compute_result_annotation(self, s_TP, s_n=None): + # basically return the same as malloc + from pypy.annotation.builtin import malloc + return malloc(s_TP, s_n) + + def specialize_call(self, hop): + from pypy.rpython.lltypesystem import lltype + # XXX assume flavor and zero to be None by now + assert hop.args_s[0].is_constant() + vlist = [hop.inputarg(lltype.Void, arg=0)] + opname = 'malloc_nonmovable' + flags = {'flavor': 'gc'} + vlist.append(hop.inputconst(lltype.Void, flags)) + + if hop.nb_args == 2: + vlist.append(hop.inputarg(lltype.Signed, arg=1)) + opname += '_varsize' + + hop.exception_cannot_occur() + return hop.genop(opname, vlist, resulttype = hop.r_result.lowleveltype) + +def resizable_buffer_of_shape(T, init_size): + """ Pre-allocates structure of type T (varsized) with possibility + to reallocate it further by resize_buffer. + """ + from pypy.rpython.lltypesystem import lltype + return lltype.malloc(T, init_size) + +class ResizableBufferOfShapeEntry(ExtRegistryEntry): + _about_ = resizable_buffer_of_shape + + def compute_result_annotation(self, s_T, s_init_size): + from pypy.annotation import model as annmodel + from pypy.rpython.lltypesystem import rffi, lltype + assert s_T.is_constant() + assert isinstance(s_init_size, annmodel.SomeInteger) + T = s_T.const + # limit ourselves to structs and to a fact that var-sized element + # does not contain pointers. + assert isinstance(T, lltype.Struct) + assert isinstance(getattr(T, T._arrayfld).OF, lltype.Primitive) + return annmodel.SomePtr(lltype.Ptr(T)) + + def specialize_call(self, hop): + from pypy.rpython.lltypesystem import lltype + flags = {'flavor': 'gc'} + vlist = [hop.inputarg(lltype.Void, 0), + hop.inputconst(lltype.Void, flags), + hop.inputarg(lltype.Signed, 1)] + hop.exception_is_here() + return hop.genop('malloc_resizable_buffer', vlist, + resulttype=hop.r_result.lowleveltype) + +def resize_buffer(ptr, old_size, new_size): + """ Resize raw buffer returned by resizable_buffer_of_shape to new size + """ + from pypy.rpython.lltypesystem import lltype + T = lltype.typeOf(ptr).TO + arrayfld = T._arrayfld + arr = getattr(ptr, arrayfld) + # we don't have any realloc on top of cpython + new_ptr = lltype.malloc(T, new_size) + new_ar = getattr(new_ptr, arrayfld) + for i in range(old_size): + new_ar[i] = arr[i] + return new_ptr + +class ResizeBufferEntry(ExtRegistryEntry): + _about_ = resize_buffer + + def compute_result_annotation(self, s_ptr, s_old_size, s_new_size): + from pypy.annotation import model as annmodel + from pypy.rpython.lltypesystem import rffi + assert isinstance(s_ptr, annmodel.SomePtr) + assert isinstance(s_new_size, annmodel.SomeInteger) + assert isinstance(s_old_size, annmodel.SomeInteger) + return s_ptr + + def specialize_call(self, hop): + from pypy.rpython.lltypesystem import lltype + vlist = [hop.inputarg(hop.args_r[0], 0), + hop.inputarg(lltype.Signed, 1), + hop.inputarg(lltype.Signed, 2)] + hop.exception_is_here() + return hop.genop('resize_buffer', vlist, + resulttype=hop.r_result.lowleveltype) + +def finish_building_buffer(ptr, final_size): + """ Finish building resizable buffer returned by resizable_buffer_of_shape + """ + return ptr + +class FinishBuildingBufferEntry(ExtRegistryEntry): + _about_ = finish_building_buffer + + def compute_result_annotation(self, s_arr, s_final_size): + from pypy.annotation.model import SomePtr, s_ImpossibleValue,\ + SomeInteger + assert isinstance(s_arr, SomePtr) + assert isinstance(s_final_size, SomeInteger) + return s_arr + + def specialize_call(self, hop): + from pypy.rpython.lltypesystem import lltype + vlist = [hop.inputarg(hop.args_r[0], 0), + hop.inputarg(hop.args_r[1], 1)] + hop.exception_cannot_occur() + return hop.genop('finish_building_buffer', vlist, + resulttype=hop.r_result.lowleveltype) Modified: pypy/dist/pypy/rlib/rsocket.py ============================================================================== --- pypy/dist/pypy/rlib/rsocket.py (original) +++ pypy/dist/pypy/rlib/rsocket.py Wed May 21 16:04:51 2008 @@ -814,14 +814,13 @@ if timeout == 1: raise SocketTimeout elif timeout == 0: - buf = mallocbuf(buffersize) + raw_buf, gc_buf = rffi.alloc_buffer(buffersize) try: - read_bytes = _c.socketrecv(self.fd, buf, buffersize, flags) + read_bytes = _c.socketrecv(self.fd, raw_buf, buffersize, flags) if read_bytes >= 0: - assert read_bytes <= buffersize - return ''.join([buf[i] for i in range(read_bytes)]) + return rffi.str_from_buffer(raw_buf, gc_buf, buffersize, read_bytes) finally: - lltype.free(buf, flavor='raw') + rffi.keep_buffer_alive_until_here(raw_buf, gc_buf) raise self.error_handler() def recvfrom(self, buffersize, flags=0): @@ -832,11 +831,11 @@ if timeout == 1: raise SocketTimeout elif timeout == 0: - buf = mallocbuf(buffersize) + raw_buf, gc_buf = rffi.alloc_buffer(buffersize) try: address, addr_p, addrlen_p = self._addrbuf() try: - read_bytes = _c.recvfrom(self.fd, buf, buffersize, flags, + read_bytes = _c.recvfrom(self.fd, raw_buf, buffersize, flags, addr_p, addrlen_p) addrlen = rffi.cast(lltype.Signed, addrlen_p[0]) finally: @@ -847,10 +846,10 @@ address.addrlen = addrlen else: address = None - data = ''.join([buf[i] for i in range(read_bytes)]) + data = rffi.str_from_buffer(raw_buf, gc_buf, buffersize, read_bytes) return (data, address) finally: - lltype.free(buf, flavor='raw') + rffi.keep_buffer_alive_until_here(raw_buf, gc_buf) raise self.error_handler() def send_raw(self, dataptr, length, flags=0): @@ -869,18 +868,18 @@ """Send a data string to the socket. For the optional flags argument, see the Unix manual. Return the number of bytes sent; this may be less than len(data) if the network is busy.""" - dataptr = rffi.str2charp(data) + dataptr = rffi.get_nonmovingbuffer(data) try: return self.send_raw(dataptr, len(data), flags) finally: - rffi.free_charp(dataptr) + rffi.free_nonmovingbuffer(data, dataptr) def sendall(self, data, flags=0): """Send a data string to the socket. For the optional flags argument, see the Unix manual. This calls send() repeatedly until all data is sent. If an error occurs, it's impossible to tell how much data has been sent.""" - dataptr = rffi.str2charp(data) + dataptr = rffi.get_nonmovingbuffer(data) try: remaining = len(data) p = dataptr @@ -889,7 +888,7 @@ p = rffi.ptradd(p, res) remaining -= res finally: - rffi.free_charp(dataptr) + rffi.free_nonmovingbuffer(data, dataptr) def sendto(self, data, flags, address): """Like send(data, flags) but allows specifying the destination @@ -1265,7 +1264,7 @@ raise RSocketError("unknown address family") if len(packed) != srcsize: raise ValueError("packed IP wrong length for inet_ntop") - srcbuf = rffi.str2charp(packed) + srcbuf = rffi.get_nonmovingbuffer(packed) try: dstbuf = mallocbuf(dstsize) try: @@ -1276,7 +1275,7 @@ finally: lltype.free(dstbuf, flavor='raw') finally: - lltype.free(srcbuf, flavor='raw') + rffi.free_nonmovingbuffer(packed, srcbuf) def setdefaulttimeout(timeout): if timeout < 0.0: Modified: pypy/dist/pypy/rlib/rstring.py ============================================================================== --- pypy/dist/pypy/rlib/rstring.py (original) +++ pypy/dist/pypy/rlib/rstring.py Wed May 21 16:04:51 2008 @@ -1,30 +1,52 @@ +""" String builder interface +""" + from pypy.rpython.extregistry import ExtRegistryEntry -from pypy.annotation import model as annmodel +from pypy.rpython.annlowlevel import llhelper + +INIT_SIZE = 100 # XXX tweak + +class AbstractStringBuilder(object): + def __init__(self, init_size=INIT_SIZE): + self.l = [] -def builder(initial_space=20): - return [] + def append(self, s): + self.l.append(s) -class SomeStringBuilder(annmodel.SomeObject): - def __init__(self, initial_space=0): - self.initial_space = initial_space + def append_slice(self, s, start, end): + self.l.append(s[start:end]) - def method_append(self, s_item): - if not isinstance(s_item, annmodel.SomeString): - raise TypeError("Can only append strings or characters to string builder") - return annmodel.SomeImpossibleValue() + def append_multiple_char(self, c, times): + self.l.append(c * times) - def method_build(self): - return annmodel.SomeString() +class StringBuilder(AbstractStringBuilder): + def build(self): + return "".join(self.l) -class StringBuilderEntry(ExtRegistryEntry): - _about_ = builder +class UnicodeBuilder(AbstractStringBuilder): + def build(self): + return u''.join(self.l) - def compute_result_annotation(self, s_initial_space=None): - if s_initial_space is None: - initial_space = 0 +class BaseEntry(object): + def compute_result_annotation(self, s_init_size=None): + from pypy.rpython.rbuilder import SomeStringBuilder, SomeUnicodeBuilder + if s_init_size is not None: + assert s_init_size.is_constant() + init_size = s_init_size.const else: - assert s_initial_space.is_constant() - initial_space = s_initial_space.const - assert isinstance(initial_space, int) - return SomeStringBuilder(initial_space) + init_size = INIT_SIZE + if self.use_unicode: + return SomeUnicodeBuilder(init_size) + return SomeStringBuilder(init_size) + + def specialize_call(self, hop): + return hop.r_result.rtyper_new(hop) + +class StringBuilderEntry(BaseEntry, ExtRegistryEntry): + _about_ = StringBuilder + use_unicode = False + +class UnicodeBuilderEntry(BaseEntry, ExtRegistryEntry): + _about_ = UnicodeBuilder + use_unicode = True Modified: pypy/dist/pypy/rlib/rzlib.py ============================================================================== --- pypy/dist/pypy/rlib/rzlib.py (original) +++ pypy/dist/pypy/rlib/rzlib.py Wed May 21 16:04:51 2008 @@ -158,9 +158,11 @@ Compute the CRC32 checksum of the string, possibly with the given start value, and return it as a unsigned 32 bit integer. """ - bytes = rffi.str2charp(string) - checksum = _crc32(start, rffi.cast(Bytefp, bytes), len(string)) - rffi.free_charp(bytes) + bytes = rffi.get_nonmovingbuffer(string) + try: + checksum = _crc32(start, rffi.cast(Bytefp, bytes), len(string)) + finally: + rffi.free_nonmovingbuffer(string, bytes) return checksum @@ -171,9 +173,11 @@ Compute the Adler-32 checksum of the string, possibly with the given start value, and return it as a unsigned 32 bit integer. """ - bytes = rffi.str2charp(string) - checksum = _adler32(start, rffi.cast(Bytefp, bytes), len(string)) - rffi.free_charp(bytes) + bytes = rffi.get_nonmovingbuffer(string) + try: + checksum = _adler32(start, rffi.cast(Bytefp, bytes), len(string)) + finally: + rffi.free_nonmovingbuffer(string, bytes) return checksum # ____________________________________________________________ Modified: pypy/dist/pypy/rlib/streamio.py ============================================================================== --- pypy/dist/pypy/rlib/streamio.py (original) +++ pypy/dist/pypy/rlib/streamio.py Wed May 21 16:04:51 2008 @@ -466,14 +466,14 @@ self.buf = "" return while self.lines: - line = self.lines[0] + line = self.lines[-1] if offset <= len(line): intoffset = intmask(offset) assert intoffset >= 0 - self.lines[0] = line[intoffset:] + self.lines[-1] = line[intoffset:] return - offset -= len(self.lines[0]) - 1 - del self.lines[0] + offset -= len(self.lines[-1]) - 1 + self.lines.pop() assert not self.lines if offset <= len(self.buf): intoffset = intmask(offset) @@ -500,6 +500,7 @@ # Skip relative to EOF by reading and saving only just as # much as needed intoffset = offset2int(offset) + self.lines.reverse() data = "\n".join(self.lines + [self.buf]) total = len(data) buffers = [data] @@ -525,6 +526,7 @@ raise StreamError("whence should be 0, 1 or 2") def readall(self): + self.lines.reverse() self.lines.append(self.buf) more = ["\n".join(self.lines)] self.lines = [] @@ -543,31 +545,33 @@ assert n >= 0 if self.lines: # See if this can be satisfied from self.lines[0] - line = self.lines[0] + line = self.lines[-1] if len(line) >= n: - self.lines[0] = line[n:] + self.lines[-1] = line[n:] return line[:n] # See if this can be satisfied *without exhausting* self.lines k = 0 i = 0 - for line in self.lines: + lgt = len(self.lines) + for linenum in range(lgt-1,-1,-1): + line = self.lines[linenum] k += len(line) if k >= n: - lines = self.lines[:i] - data = self.lines[i] + lines = self.lines[linenum + 1:] + data = self.lines[linenum] cutoff = len(data) - (k-n) assert cutoff >= 0 lines.append(data[:cutoff]) - del self.lines[:i] - self.lines[0] = data[cutoff:] + del self.lines[linenum:] + self.lines.append(data[cutoff:]) return "\n".join(lines) k += 1 - i += 1 # See if this can be satisfied from self.lines plus self.buf if k + len(self.buf) >= n: lines = self.lines + lines.reverse() self.lines = [] cutoff = n - k assert cutoff >= 0 @@ -587,6 +591,7 @@ return data[:cutoff] lines = self.lines + lines.reverse() self.lines = [] lines.append(self.buf) self.buf = "" @@ -608,16 +613,39 @@ more[-1] = data[:cutoff] return "".join(more) + # read_next_bunch is generally this, version below is slightly faster + #def _read_next_bunch(self): + # self.lines = self.buf.split("\n") + # self.buf = self.lines.pop() + # self.lines.reverse() + + def _read_next_bunch(self): + numlines = self.buf.count("\n") + self.lines = [None] * numlines + last = -1 + num = numlines - 1 + while True: + start = last + 1 + assert start >= 0 + next = self.buf.find("\n", start) + if next == -1: + if last != -1: + self.buf = self.buf[start:] + break + assert next >= 0 + self.lines[num] = self.buf[start:next] + last = next + num -= 1 + def readline(self): if self.lines: - return self.lines.pop(0) + "\n" + return self.lines.pop() + "\n" # This block is needed because read() can leave self.buf # containing newlines - self.lines = self.buf.split("\n") - self.buf = self.lines.pop() + self._read_next_bunch() if self.lines: - return self.lines.pop(0) + "\n" + return self.lines.pop() + "\n" if self.buf: buf = [self.buf] @@ -625,10 +653,9 @@ buf = [] while 1: self.buf = self.do_read(self.bufsize) - self.lines = self.buf.split("\n") - self.buf = self.lines.pop() + self._read_next_bunch() if self.lines: - buf.append(self.lines.pop(0)) + buf.append(self.lines.pop()) buf.append("\n") break if not self.buf: @@ -639,7 +666,7 @@ def peek(self): if self.lines: - return self.lines[0] + "\n" + return self.lines[-1] + "\n" else: return self.buf Modified: pypy/dist/pypy/rlib/test/test_rgc.py ============================================================================== --- pypy/dist/pypy/rlib/test/test_rgc.py (original) +++ pypy/dist/pypy/rlib/test/test_rgc.py Wed May 21 16:04:51 2008 @@ -1,6 +1,8 @@ from pypy.rpython.test.test_llinterp import gengraph, interpret +from pypy.rpython.lltypesystem import lltype from pypy.rlib import rgc # Force registration of gc.collect import gc +import py def test_collect(): def f(): @@ -17,3 +19,33 @@ assert res is None +def test_can_move(): + T0 = lltype.GcStruct('T') + T1 = lltype.GcArray(lltype.Float) + def f(i): + if i: + return rgc.can_move(lltype.malloc(T0)) + else: + return rgc.can_move(lltype.malloc(T1, 1)) + + t, typer, graph = gengraph(f, [int]) + ops = list(graph.iterblockops()) + res = [op for op in ops if op[1].opname == 'gc_can_move'] + assert len(res) == 2 + + res = interpret(f, [1]) + + assert res == True + +def test_resizable_buffer(): + from pypy.rpython.lltypesystem.rstr import STR + from pypy.rpython.annlowlevel import hlstr + + def f(): + ptr = rgc.resizable_buffer_of_shape(STR, 1) + ptr.chars[0] = 'a' + ptr = rgc.resize_buffer(ptr, 1, 2) + ptr.chars[1] = 'b' + return hlstr(rgc.finish_building_buffer(ptr, 2)) + + assert f() == 'ab' Modified: pypy/dist/pypy/rlib/test/test_rsocket.py ============================================================================== --- pypy/dist/pypy/rlib/test/test_rsocket.py (original) +++ pypy/dist/pypy/rlib/test/test_rsocket.py Wed May 21 16:04:51 2008 @@ -1,6 +1,7 @@ import py, errno, sys from pypy.rlib import rsocket from pypy.rlib.rsocket import * +from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin import socket as cpy_socket # cannot test error codes in Win32 because ll2ctypes doesn't save @@ -268,12 +269,12 @@ def test_getaddrinfo_no_reverse_lookup(): # It seems that getaddrinfo never runs a reverse lookup on Linux. # Python2.3 on Windows returns the hostname. - lst = getaddrinfo('134.99.112.214', None, flags=AI_NUMERICHOST) + lst = getaddrinfo('213.239.226.252', None, flags=AI_NUMERICHOST) assert isinstance(lst, list) found = False for family, socktype, protocol, canonname, addr in lst: - assert canonname != 'snake.cs.uni-duesseldorf.de' - if addr.get_host() == '134.99.112.214': + assert canonname != 'codespeak.net' + if addr.get_host() == '213.239.226.252': found = True assert found, lst @@ -370,7 +371,6 @@ clientsock.close() s.close() - class TestTCP: PORT = 50007 HOST = 'localhost' Modified: pypy/dist/pypy/rlib/test/test_rstring.py ============================================================================== --- pypy/dist/pypy/rlib/test/test_rstring.py (original) +++ pypy/dist/pypy/rlib/test/test_rstring.py Wed May 21 16:04:51 2008 @@ -1,27 +1,20 @@ -from pypy.translator.translator import TranslationContext -from pypy.rlib import rstring -from pypy.annotation import model as annmodel +from pypy.rlib.rstring import StringBuilder, UnicodeBuilder -class TestAnnotationStringBuilder: - def annotate(self, func, args): - t = TranslationContext() - res = t.buildannotator().build_types(func, args) - return t, res +def test_string_builder(): + s = StringBuilder() + s.append("a") + s.append("abc") + s.append("a") + s.append_slice("abc", 1, 2) + s.append_multiple_char('d', 4) + assert s.build() == "aabcabdddd" - def test_builder(self): - def f(): - return rstring.builder() - - t, res = self.annotate(f, []) - assert isinstance(res, rstring.SomeStringBuilder) - - def test_methods(self): - def f(x): - b = rstring.builder() - for i in range(x): - b.append("abc") - return b.build() - - t, res = self.annotate(f, [int]) - assert isinstance(res, annmodel.SomeString) +def test_unicode_builder(): + s = UnicodeBuilder() + s.append(u'a') + s.append(u'abc') + s.append_slice(u'abcdef', 1, 2) + s.append_multiple_char('d', 4) + assert s.build() == 'aabcbdddd' + assert isinstance(s.build(), unicode) Modified: pypy/dist/pypy/rpython/annlowlevel.py ============================================================================== --- pypy/dist/pypy/rpython/annlowlevel.py (original) +++ pypy/dist/pypy/rpython/annlowlevel.py Wed May 21 16:04:51 2008 @@ -400,6 +400,28 @@ return hop.genop('same_as', [v_ll_str], resulttype = hop.r_result.lowleveltype) +def llstr(s): + from pypy.rpython.lltypesystem.rstr import mallocstr + # XXX not sure what to do with ootypesystem + ll_s = mallocstr(len(s)) + for i, c in enumerate(s): + ll_s.chars[i] = c + return ll_s + +class LLStrEntry(extregistry.ExtRegistryEntry): + _about_ = llstr + + def compute_result_annotation(self, s_str): + from pypy.rpython.lltypesystem.rstr import STR + return annmodel.lltype_to_annotation(lltype.Ptr(STR)) + + def specialize_call(self, hop): + hop.exception_cannot_occur() + assert hop.args_r[0].lowleveltype == hop.r_result.lowleveltype + v_ll_str, = hop.inputargs(*hop.args_r) + return hop.genop('same_as', [v_ll_str], + resulttype = hop.r_result.lowleveltype) + # ____________________________________________________________ def cast_object_to_ptr(PTR, object): Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Wed May 21 16:04:51 2008 @@ -673,13 +673,6 @@ self.llinterpreter.remember_malloc(ptr, self) return ptr - def op_coalloc(self, obj, coallocator, flags): - flavor = flags['flavor'] - assert flavor == "gc" - zero = flags.get('zero', False) - ptr = self.heap.coalloc(obj, coallocator, zero=zero) - return ptr - def op_malloc_varsize(self, obj, flags, size): flavor = flags['flavor'] zero = flags.get('zero', False) @@ -691,14 +684,27 @@ return ptr except MemoryError: self.make_llexception() - - def op_coalloc_varsize(self, obj, coallocator, flags, size): + + def op_malloc_nonmovable(self, obj, flags): flavor = flags['flavor'] + assert flavor == 'gc' zero = flags.get('zero', False) - assert flavor == "gc" + return self.heap.malloc_nonmovable(obj, zero=zero) + + def op_malloc_nonmovable_varsize(self, obj, flags, size): + flavor = flags['flavor'] + assert flavor == 'gc' zero = flags.get('zero', False) - ptr = self.heap.coalloc(obj, coallocator, size, zero=zero) - return ptr + return self.heap.malloc_nonmovable(obj, size, zero=zero) + + def op_malloc_resizable_buffer(self, obj, flags, size): + return self.heap.malloc_resizable_buffer(obj, size) + + def op_resize_buffer(self, obj, old_size, new_size): + return self.heap.resize_buffer(obj, old_size, new_size) + + def op_finish_building_buffer(self, obj, size): + return self.heap.finish_building_buffer(obj, size) def op_free(self, obj, flavor): assert isinstance(flavor, str) @@ -716,6 +722,11 @@ lltype.ContainerType) return getattr(obj, field) + def op_force_cast(self, RESTYPE, obj): + from pypy.rpython.lltypesystem import ll2ctypes + return ll2ctypes.force_cast(RESTYPE, obj) + op_force_cast.need_result_type = True + def op_cast_int_to_ptr(self, RESTYPE, int1): return lltype.cast_int_to_ptr(RESTYPE, int1) op_cast_int_to_ptr.need_result_type = True @@ -759,6 +770,9 @@ def op_gc__enable_finalizers(self): self.heap.enable_finalizers() + def op_gc_can_move(self, addr): + return self.heap.can_move(addr) + def op_gc_free(self, addr): # what can you do? pass Modified: pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py Wed May 21 16:04:51 2008 @@ -204,7 +204,11 @@ return # regular case: allocate a new ctypes Structure of the proper type cls = get_ctypes_type(STRUCT) - cstruct = cls._malloc() + if STRUCT._arrayfld: + n = len(getattr(container, STRUCT._arrayfld).items) + else: + n = None + cstruct = cls._malloc(n) add_storage(container, _struct_mixin, cstruct) for field_name in STRUCT._names: FIELDTYPE = getattr(STRUCT, field_name) @@ -218,7 +222,9 @@ csubstruct = getattr(cstruct, field_name) convert_struct(field_value, csubstruct) else: - raise NotImplementedError('inlined field', FIELDTYPE) + csubarray = getattr(cstruct, field_name) + convert_array(field_value, csubarray) + #raise NotImplementedError('inlined field', FIELDTYPE) remove_regular_struct_content(container) def remove_regular_struct_content(container): @@ -228,15 +234,19 @@ if not isinstance(FIELDTYPE, lltype.ContainerType): delattr(container, field_name) -def convert_array(container): +def convert_array(container, carray=None): ARRAY = container._TYPE cls = get_ctypes_type(ARRAY) - carray = cls._malloc(container.getlength()) + if carray is None: + carray = cls._malloc(container.getlength()) add_storage(container, _array_mixin, carray) if not isinstance(ARRAY.OF, lltype.ContainerType): + # fish that we have enough space + ctypes_array = ctypes.cast(carray.items, + ctypes.POINTER(carray.items._type_)) for i in range(container.getlength()): item_value = container.items[i] # fish fish - carray.items[i] = lltype2ctypes(item_value) + ctypes_array[i] = lltype2ctypes(item_value) remove_regular_array_content(container) else: assert isinstance(ARRAY.OF, lltype.Struct) @@ -255,7 +265,10 @@ remove_regular_struct_content(container) for field_name in STRUCT._names: FIELDTYPE = getattr(STRUCT, field_name) - if isinstance(FIELDTYPE, lltype.ContainerType): + if isinstance(FIELDTYPE, lltype.Array): + convert_array(getattr(container, field_name), + getattr(ctypes_storage, field_name)) + elif isinstance(FIELDTYPE, lltype.ContainerType): struct_use_ctypes_storage(getattr(container, field_name), getattr(ctypes_storage, field_name)) @@ -375,6 +388,22 @@ # ____________________________________________________________ +def _find_parent(llobj): + parent, parentindex = lltype.parentlink(llobj) + if parent is None: + return llobj, 0 + next_p, next_i = _find_parent(parent) + if isinstance(parentindex, int): + c_tp = get_ctypes_type(lltype.typeOf(parent)) + sizeof = ctypes.sizeof(get_ctypes_type(lltype.typeOf(parent).OF)) + ofs = c_tp.items.offset + parentindex * sizeof + return next_p, next_i + ofs + else: + c_tp = get_ctypes_type(lltype.typeOf(parent)) + ofs = getattr(c_tp, parentindex).offset + return next_p, next_i + ofs + + # XXX THIS IS A HACK XXX # ctypes does not keep callback arguments alive. So we do. Forever # we need to think deeper how to approach this problem @@ -418,6 +447,11 @@ if T.TO._gckind != 'raw' and not T.TO._hints.get('callback', None): raise Exception("can only pass 'raw' data structures to C, not %r" % (T.TO._gckind,)) + + index = 0 + if isinstance(container, lltype._subarray): + topmost, index = _find_parent(container) + container = topmost if container._storage is None: raise RuntimeError("attempting to pass a freed structure to C") if container._storage is True: @@ -434,7 +468,17 @@ container._ctypes_storage_was_allocated() storage = container._storage p = ctypes.pointer(storage) - if normalize and hasattr(storage, '_normalized_ctype'): + if index: + p = ctypes.cast(p, ctypes.c_void_p) + p = ctypes.c_void_p(p.value + index) + c_tp = get_ctypes_type(T.TO) + storage._normalized_ctype = c_tp + if normalize and getattr(T.TO, '_arrayfld', None): + # XXX doesn't cache + c_tp = build_ctypes_struct(T.TO, [], + len(getattr(storage, T.TO._arrayfld).items)) + p = ctypes.cast(p, ctypes.POINTER(c_tp)) + elif normalize and hasattr(storage, '_normalized_ctype'): p = ctypes.cast(p, ctypes.POINTER(storage._normalized_ctype)) return p @@ -449,7 +493,6 @@ if T is lltype.SingleFloat: return ctypes.c_float(float(llobj)) - return llobj def ctypes2lltype(T, cobj): @@ -461,8 +504,10 @@ return lltype.nullptr(T.TO) if isinstance(T.TO, lltype.Struct): if T.TO._arrayfld is not None: - raise NotImplementedError("XXX var-sized structs") - container = lltype._struct(T.TO) + lgt = getattr(cobj.contents, T.TO._arrayfld).length + container = lltype._struct(T.TO, lgt) + else: + container = lltype._struct(T.TO) struct_use_ctypes_storage(container, cobj.contents) elif isinstance(T.TO, lltype.Array): if T.TO._hints.get('nolength', False): @@ -647,6 +692,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.fakeaddress): + value = value.ptr TYPE1 = lltype.typeOf(value) cvalue = lltype2ctypes(value) cresulttype = get_ctypes_type(RESTYPE) @@ -682,14 +729,12 @@ return annmodel.lltype_to_annotation(RESTYPE) def specialize_call(self, hop): - from pypy.rpython.rbuiltin import gen_cast hop.exception_cannot_occur() s_RESTYPE = hop.args_s[0] assert s_RESTYPE.is_constant() RESTYPE = s_RESTYPE.const v_arg = hop.inputarg(hop.args_r[1], arg=1) - TYPE1 = v_arg.concretetype - return gen_cast(hop.llops, RESTYPE, v_arg) + return hop.genop('force_cast', [v_arg], resulttype = RESTYPE) def typecheck_ptradd(T): # --- ptradd() is only for pointers to non-GC, no-length arrays. Modified: pypy/dist/pypy/rpython/lltypesystem/ll_str.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/ll_str.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/ll_str.py Wed May 21 16:04:51 2008 @@ -1,4 +1,5 @@ from pypy.rpython.lltypesystem.lltype import GcArray, Array, Char, malloc +from pypy.rpython.annlowlevel import llstr from pypy.rlib.rarithmetic import r_uint, formatd CHAR_ARRAY = GcArray(Char) @@ -115,5 +116,5 @@ return result def ll_float_str(repr, f): - return formatd("%f", f) + return llstr(formatd("%f", f)) Modified: pypy/dist/pypy/rpython/lltypesystem/llheap.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/llheap.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/llheap.py Wed May 21 16:04:51 2008 @@ -6,6 +6,7 @@ setfield = setattr from operator import setitem as setarrayitem from pypy.rlib.rgc import collect, disable_finalizers, enable_finalizers +from pypy.rlib.rgc import can_move def setinterior(toplevelcontainer, inneraddr, INNERTYPE, newvalue): assert typeOf(newvalue) == INNERTYPE @@ -17,6 +18,19 @@ def weakref_create_getlazy(objgetter): return weakref_create(objgetter()) -def coalloc(T, coallocator, n=None, zero=True): - # ignore the coallocator - return malloc(T, n, zero=zero) +malloc_nonmovable = malloc + +def malloc_resizable_buffer(TP, size): + return malloc(TP, size) + +def resize_buffer(buf, old_size, new_size): + ll_str = malloc(typeOf(buf).TO, new_size) + for i in range(old_size): + ll_str.chars[i] = buf.chars[i] + return ll_str + +def finish_building_buffer(buf, final_size): + ll_str = malloc(typeOf(buf).TO, final_size) + for i in range(final_size): + ll_str.chars[i] = buf.chars[i] + return ll_str Modified: pypy/dist/pypy/rpython/lltypesystem/llmemory.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/llmemory.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/llmemory.py Wed May 21 16:04:51 2008 @@ -256,6 +256,7 @@ assert array_type_match(lltype.typeOf(arrayptr).TO, self.TYPE) if isinstance(self.TYPE.OF, lltype.ContainerType): # XXX this doesn't support empty arrays + # XXX it's also missing 'solid' support, probably o = arrayptr._obj.getitem(0) return o._as_ptr() else: Modified: pypy/dist/pypy/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/lloperation.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/lloperation.py Wed May 21 16:04:51 2008 @@ -317,13 +317,17 @@ 'cast_float_to_uint': LLOp(canfold=True), # XXX need OverflowError? 'cast_float_to_longlong':LLOp(canfold=True), 'truncate_longlong_to_int':LLOp(canfold=True), + 'force_cast': LLOp(sideeffects=False), # only for rffi.cast() # __________ pointer operations __________ 'malloc': LLOp(canraise=(MemoryError,), canunwindgc=True), 'malloc_varsize': LLOp(canraise=(MemoryError,), canunwindgc=True), - 'coalloc': LLOp(canraise=(MemoryError,), canunwindgc=True), - 'coalloc_varsize': LLOp(canraise=(MemoryError,), canunwindgc=True), + 'malloc_nonmovable': LLOp(canraise=(MemoryError,), canunwindgc=True), + 'malloc_nonmovable_varsize':LLOp(canraise=(MemoryError,),canunwindgc=True), + 'malloc_resizable_buffer': LLOp(canraise=(MemoryError,),canunwindgc=True), + 'resize_buffer': LLOp(canraise=(MemoryError,),canunwindgc=True), + 'finish_building_buffer' : LLOp(), 'zero_gc_pointers_inside': LLOp(), 'free': LLOp(), 'getfield': LLOp(sideeffects=False, canrun=True), @@ -399,6 +403,7 @@ 'gc_reload_possibly_moved': LLOp(), 'gc_id': LLOp(canraise=(MemoryError,), sideeffects=False), 'gc_set_max_heap_size': LLOp(), + 'gc_can_move' : LLOp(sideeffects=False), # experimental operations in support of thread cloning, only # implemented by the Mark&Sweep GC 'gc_x_swap_pool': LLOp(canraise=(MemoryError,), canunwindgc=True), Modified: pypy/dist/pypy/rpython/lltypesystem/lltype.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/lltype.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/lltype.py Wed May 21 16:04:51 2008 @@ -1514,9 +1514,16 @@ def __init__(self, TYPE, parent, baseoffset_or_fieldname): _parentable.__init__(self, TYPE) self._setparentstructure(parent, baseoffset_or_fieldname) + # Keep the parent array alive, we share the same allocation. + # Don't do it if we are inside a GC object, though -- it's someone + # else's job to keep the GC object alive + if typeOf(top_container(parent))._gckind == 'raw': + self._keepparent = parent def __repr__(self): - + parent = self._wrparent() + if parent is None: + return '<_subarray at %s in already freed>' % (self._parent_index,) return '<_subarray at %r in %r>' % (self._parent_index, self._parentstructure(check=False)) Modified: pypy/dist/pypy/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rffi.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rffi.py Wed May 21 16:04:51 2008 @@ -2,17 +2,23 @@ from pypy.annotation import model as annmodel 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.annotation.model import lltype_to_annotation from pypy.tool.sourcetools import func_with_new_name from pypy.rlib.objectmodel import Symbolic, CDefinedIntSymbolic -from pypy.rlib import rarithmetic +from pypy.rlib.objectmodel import keepalive_until_here +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.translator.backendopt.canraise import RaiseAnalyzer -from pypy.rpython.annlowlevel import llhelper +from pypy.rpython.annlowlevel import llhelper, llstr, hlstr +from pypy.rpython.lltypesystem.rstr import STR +from pypy.rlib.objectmodel import we_are_translated +from pypy.rpython.lltypesystem import llmemory import os, sys class UnhandledRPythonException(Exception): @@ -470,6 +476,95 @@ l.append(cp[i]) i += 1 return "".join(l) + +# str -> char* +def get_nonmovingbuffer(data): + """ + Either returns a non-moving copy or performs neccessary pointer arithmetic + to return a pointer to the characters of a string if the string is already + nonmovable. + Must be followed by a free_nonmovingbuffer call. + """ + if rgc.can_move(data): + count = len(data) + buf = lltype.malloc(CCHARP.TO, count, flavor='raw') + for i in range(count): + buf[i] = data[i] + return buf + else: + data_start = cast_ptr_to_adr(llstr(data)) + \ + offsetof(STR, 'chars') + itemoffsetof(STR.chars, 0) + return cast(CCHARP, data_start) + +# (str, char*) -> None +def free_nonmovingbuffer(data, buf): + """ + Either free a non-moving buffer or keep the original storage alive. + """ + if rgc.can_move(data): + lltype.free(buf, flavor='raw') + else: + keepalive_until_here(data) + +# int -> (char*, str) +def alloc_buffer(count): + """ + Returns a (raw_buffer, gc_buffer) pair, allocated with count bytes. + The raw_buffer can be safely passed to a native function which expects it + to not move. Call str_from_buffer with the returned values to get a safe + high-level string. When the garbage collector cooperates, this allows for + the process to be performed without an extra copy. + Make sure to call keep_buffer_alive_until_here on the returned values. + """ + str_chars_offset = offsetof(STR, 'chars') + itemoffsetof(STR.chars, 0) + gc_buf = rgc.malloc_nonmovable(STR, count) + if gc_buf: + realbuf = cast_ptr_to_adr(gc_buf) + str_chars_offset + raw_buf = cast(CCHARP, realbuf) + return raw_buf, gc_buf + else: + raw_buf = lltype.malloc(CCHARP.TO, count, flavor='raw') + return raw_buf, lltype.nullptr(STR) +alloc_buffer._always_inline_ = True # to get rid of the returned tuple obj + +# (char*, str, int, int) -> None +def str_from_buffer(raw_buf, gc_buf, allocated_size, needed_size): + """ + Converts from a pair returned by alloc_buffer to a high-level string. + The returned string will be truncated to needed_size. + """ + assert allocated_size >= needed_size + + if gc_buf and (allocated_size == needed_size): + return hlstr(gc_buf) + + new_buf = lltype.malloc(STR, needed_size) + try: + str_chars_offset = offsetof(STR, 'chars') + itemoffsetof(STR.chars, 0) + if gc_buf: + src = cast_ptr_to_adr(gc_buf) + str_chars_offset + else: + src = cast_ptr_to_adr(raw_buf) + dest = cast_ptr_to_adr(new_buf) + str_chars_offset + ## FIXME: This is bad, because dest could potentially move + ## if there are threads involved. + raw_memcopy(src, dest, + llmemory.sizeof(lltype.Char) * needed_size) + return hlstr(new_buf) + finally: + keepalive_until_here(new_buf) + +# (char*, str) -> None +def keep_buffer_alive_until_here(raw_buf, gc_buf): + """ + Keeps buffers alive or frees temporary buffers created by alloc_buffer. + This must be called after a call to alloc_buffer, usually in a try/finally + block. + """ + if gc_buf: + keepalive_until_here(gc_buf) + elif raw_buf: + lltype.free(raw_buf, flavor='raw') # char* -> str, with an upper bound on the length in case there is no \x00 def charp2strn(cp, maxlen): Modified: pypy/dist/pypy/rpython/lltypesystem/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rstr.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rstr.py Wed May 21 16:04:51 2008 @@ -15,6 +15,8 @@ Bool, Void, GcArray, nullptr, pyobjectptr, cast_primitive, typeOf,\ staticAdtMethod, GcForwardReference from pypy.rpython.rmodel import Repr +from pypy.rpython.lltypesystem import llmemory +from pypy.tool.sourcetools import func_with_new_name # ____________________________________________________________ # @@ -28,7 +30,7 @@ STR = GcForwardReference() UNICODE = GcForwardReference() -def new_malloc(TP): +def new_malloc(TP, name): def mallocstr(length): ll_assert(length >= 0, "negative string length") r = malloc(TP, length) @@ -36,10 +38,10 @@ r.hash = 0 return r mallocstr._annspecialcase_ = 'specialize:semierased' - return mallocstr + return func_with_new_name(mallocstr, name) -mallocstr = new_malloc(STR) -mallocunicode = new_malloc(UNICODE) +mallocstr = new_malloc(STR, 'mallocstr') +mallocunicode = new_malloc(UNICODE, 'mallocunicode') def emptystrfun(): return emptystr @@ -47,14 +49,35 @@ def emptyunicodefun(): return emptyunicode +def _new_copy_contents_fun(TP, CHAR_TP, name): + def _str_ofs(item): + return (llmemory.offsetof(TP, 'chars') + + llmemory.itemoffsetof(TP.chars, 0) + + llmemory.sizeof(CHAR_TP) * item) + + def copy_string_contents(s1, s2, s1start, s2start, lgt): + assert s1start >= 0 + assert s2start >= 0 + assert lgt >= 0 + src = llmemory.cast_ptr_to_adr(s1) + _str_ofs(s1start) + dest = llmemory.cast_ptr_to_adr(s2) + _str_ofs(s2start) + llmemory.raw_memcopy(src, dest, llmemory.sizeof(CHAR_TP) * lgt) + copy_string_contents._always_inline_ = True + return func_with_new_name(copy_string_contents, 'copy_%s_contents' % name) + +copy_string_contents = _new_copy_contents_fun(STR, Char, 'string') +copy_unicode_contents = _new_copy_contents_fun(UNICODE, UniChar, 'unicode') + STR.become(GcStruct('rpy_string', ('hash', Signed), ('chars', Array(Char, hints={'immutable': True})), adtmeths={'malloc' : staticAdtMethod(mallocstr), - 'empty' : staticAdtMethod(emptystrfun)})) + 'empty' : staticAdtMethod(emptystrfun), + 'copy_contents' : staticAdtMethod(copy_string_contents)})) UNICODE.become(GcStruct('rpy_unicode', ('hash', Signed), ('chars', Array(UniChar, hints={'immutable': True})), adtmeths={'malloc' : staticAdtMethod(mallocunicode), - 'empty' : staticAdtMethod(emptyunicodefun)} + 'empty' : staticAdtMethod(emptyunicodefun), + 'copy_contents' : staticAdtMethod(copy_unicode_contents)} )) SIGNED_ARRAY = GcArray(Signed) CONST_STR_CACHE = WeakValueDictionary() @@ -217,6 +240,7 @@ times = 0 newstr = malloc(times) j = 0 + # XXX we can use memset here, not sure how useful this is while j < times: newstr.chars[j] = ch j += 1 @@ -268,15 +292,8 @@ len1 = len(s1.chars) len2 = len(s2.chars) newstr = s1.malloc(len1 + len2) - j = 0 - while j < len1: - newstr.chars[j] = s1.chars[j] - j += 1 - i = 0 - while i < len2: - newstr.chars[j] = s2.chars[i] - i += 1 - j += 1 + s1.copy_contents(s1, newstr, 0, 0, len1) + s1.copy_contents(s2, newstr, 0, len1, len2) return newstr def ll_strip(s, ch, left, right): @@ -293,12 +310,7 @@ rpos -= 1 r_len = rpos - lpos + 1 result = s.malloc(r_len) - i = 0 - j = lpos - while i < r_len: - result.chars[i] = s.chars[j] - i += 1 - j += 1 + s.copy_contents(s, result, lpos, 0, r_len) return result def ll_upper(s): @@ -307,7 +319,8 @@ if s_len == 0: return s.empty() i = 0 - result = s.malloc(s_len) + result = mallocstr(s_len) + # ^^^^^^^^^ specifically to explode on unicode while i < s_len: ch = s_chars[i] if 'a' <= ch <= 'z': @@ -322,7 +335,8 @@ if s_len == 0: return s.empty() i = 0 - result = s.malloc(s_len) + result = mallocstr(s_len) + # ^^^^^^^^^ specifically to explode on unicode while i < s_len: ch = s_chars[i] if 'A' <= ch <= 'Z': @@ -343,31 +357,15 @@ itemslen += len(items[i].chars) i += 1 result = s.malloc(itemslen + s_len * (num_items - 1)) - res_chars = result.chars - res_index = 0 - i = 0 - item_chars = items[i].chars - item_len = len(item_chars) - j = 0 - while j < item_len: - res_chars[res_index] = item_chars[j] - j += 1 - res_index += 1 - i += 1 + res_index = len(items[0].chars) + s.copy_contents(items[0], result, 0, 0, res_index) + i = 1 while i < num_items: - j = 0 - while j < s_len: - res_chars[res_index] = s_chars[j] - j += 1 - res_index += 1 - - item_chars = items[i].chars - item_len = len(item_chars) - j = 0 - while j < item_len: - res_chars[res_index] = item_chars[j] - j += 1 - res_index += 1 + s.copy_contents(s, result, 0, res_index, s_len) + res_index += s_len + lgt = len(items[i].chars) + s.copy_contents(items[i], result, 0, res_index, lgt) + res_index += lgt i += 1 return result @@ -599,8 +597,10 @@ i += 1 if typeOf(items).TO.OF.TO == STR: malloc = mallocstr + copy_contents = copy_string_contents else: malloc = mallocunicode + copy_contents = copy_unicode_contents result = malloc(itemslen) res_chars = result.chars res_index = 0 @@ -608,15 +608,14 @@ while i < num_items: item_chars = items[i].chars item_len = len(item_chars) - j = 0 - while j < item_len: - res_chars[res_index] = item_chars[j] - j += 1 - res_index += 1 + copy_contents(items[i], result, 0, res_index, item_len) + res_index += item_len i += 1 return result def ll_join_chars(length, chars): + # no need to optimize this, will be replaced by string builder + # at some point soon num_chars = length if typeOf(chars).TO.OF == Char: malloc = mallocstr @@ -633,11 +632,10 @@ def ll_stringslice_startonly(s1, start): len1 = len(s1.chars) newstr = s1.malloc(len1 - start) - j = 0 - while start < len1: - newstr.chars[j] = s1.chars[start] - start += 1 - j += 1 + lgt = len1 - start + assert lgt >= 0 + assert start >= 0 + s1.copy_contents(s1, newstr, start, 0, lgt) return newstr def ll_stringslice(s1, slice): @@ -648,20 +646,17 @@ return s1 stop = len(s1.chars) newstr = s1.malloc(stop - start) - j = 0 - while start < stop: - newstr.chars[j] = s1.chars[start] - start += 1 - j += 1 + assert start >= 0 + lgt = stop - start + assert lgt >= 0 + s1.copy_contents(s1, newstr, start, 0, lgt) return newstr def ll_stringslice_minusone(s1): newlen = len(s1.chars) - 1 newstr = s1.malloc(newlen) - j = 0 - while j < newlen: - newstr.chars[j] = s1.chars[j] - j += 1 + assert newlen >= 0 + s1.copy_contents(s1, newstr, 0, 0, newlen) return newstr def ll_split_chr(LIST, s, c): @@ -681,22 +676,12 @@ while j < strlen: if chars[j] == c: item = items[resindex] = s.malloc(j - i) - newchars = item.chars - k = i - while k < j: - newchars[k - i] = chars[k] - k += 1 + item.copy_contents(s, item, i, 0, j - i) resindex += 1 i = j + 1 j += 1 item = items[resindex] = s.malloc(j - i) - newchars = item.chars - k = i - while k < j: - newchars[k - i] = chars[k] - k += 1 - resindex += 1 - + item.copy_contents(s, item, i, 0, j - i) return res def ll_replace_chr_chr(s, c1, c2): Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_ll2ctypes.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/test/test_ll2ctypes.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/test/test_ll2ctypes.py Wed May 21 16:04:51 2008 @@ -6,11 +6,12 @@ from pypy.rpython.lltypesystem.ll2ctypes import lltype2ctypes, ctypes2lltype from pypy.rpython.lltypesystem.ll2ctypes import standard_c_lib from pypy.rpython.lltypesystem.ll2ctypes import uninitialized2ctypes -from pypy.rpython.lltypesystem.ll2ctypes import ALLOCATED +from pypy.rpython.lltypesystem.ll2ctypes import ALLOCATED, force_cast from pypy.rpython.annlowlevel import llhelper from pypy.rlib import rposix from pypy.translator.tool.cbuild import ExternalCompilationInfo from pypy.tool.udir import udir +from pypy.rpython.test.test_llinterp import interpret class TestLL2Ctypes(object): @@ -109,6 +110,19 @@ lltype.free(a, flavor='raw') assert not ALLOCATED # detects memory leaks in the test + def test_array_inside_struct(self): + # like rstr.STR, but not Gc + STR = lltype.Struct('STR', ('x', lltype.Signed), ('y', lltype.Array(lltype.Char))) + a = lltype.malloc(STR, 3, flavor='raw') + a.y[0] = 'x' + a.y[1] = 'y' + a.y[2] = 'z' + ac = lltype2ctypes(a) + assert ac.contents.y.length == 3 + assert ac.contents.y.items[2] == ord('z') + lltype.free(a, flavor='raw') + assert not ALLOCATED + def test_array_nolength(self): A = lltype.Array(lltype.Signed, hints={'nolength': True}) a = lltype.malloc(A, 10, flavor='raw') @@ -362,6 +376,20 @@ lltype.free(a, flavor='raw') assert not ALLOCATED # detects memory leaks in the test + def test_adr_cast(self): + from pypy.rpython.annlowlevel import llstr + from pypy.rpython.lltypesystem.rstr import STR + P = lltype.Ptr(lltype.FixedSizeArray(lltype.Char, 1)) + def f(): + a = llstr("xyz") + b = (llmemory.cast_ptr_to_adr(a) + llmemory.offsetof(STR, 'chars') + + llmemory.itemoffsetof(STR.chars, 0)) + buf = rffi.cast(rffi.VOIDP, b) + return buf[2] + assert f() == 'z' + res = interpret(f, []) + assert res == 'z' + def test_funcptr1(self): def dummy(n): return n+1 @@ -798,3 +826,13 @@ c1 = lltype2ctypes(a1) c2 = lltype2ctypes(a2) assert type(c1) is type(c2) + + def test_varsized_struct(self): + STR = lltype.Struct('rpy_string', ('hash', lltype.Signed), + ('chars', lltype.Array(lltype.Char, hints={'immutable': True}))) + s = lltype.malloc(STR, 3, flavor='raw') + one = force_cast(rffi.VOIDP, s) + # sanity check + #assert lltype2ctypes(one).contents.items._length_ > 0 + two = force_cast(lltype.Ptr(STR), one) + assert s == two Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py Wed May 21 16:04:51 2008 @@ -602,3 +602,13 @@ py.test.raises(TypeError, "sizeof(S1) <= 0") py.test.raises(TypeError, "sizeof(S1) <= 4") py.test.raises(TypeError, "(-sizeof(S1)) >= 0") + +def test_addr_keeps_object_alive(): + A = lltype.Array(Address) + ptr = lltype.malloc(A, 10, immortal=True) + adr = cast_ptr_to_adr(ptr) + ArrayItemsOffset(A) + del ptr + import gc; gc.collect(); gc.collect() + # the following line crashes if the array is dead + ptr1 = cast_adr_to_ptr(adr, lltype.Ptr(lltype.FixedSizeArray(Address, 1))) + ptr1[0] = NULL Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_lltype.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/test/test_lltype.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/test/test_lltype.py Wed May 21 16:04:51 2008 @@ -727,3 +727,11 @@ setattr(s, word, i) for i, word in enumerate(words): assert getattr(s, word) == i + +def test_subarray_keeps_array_alive(): + A = Array(Signed) + ptr = malloc(A, 10, immortal=True) + ptr2 = direct_arrayitems(ptr) + del ptr + import gc; gc.collect(); gc.collect() + ptr2[0] = 5 # crashes if the array was deallocated Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_rffi.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/test/test_rffi.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/test/test_rffi.py Wed May 21 16:04:51 2008 @@ -7,9 +7,11 @@ from pypy.translator.c.test.test_genc import compile as compile_c from pypy.translator.llvm.test.runtest import compile_function as compile_llvm from pypy.rpython.lltypesystem.lltype import Signed, Ptr, Char, malloc +from pypy.rpython.lltypesystem.rstr import STR from pypy.rpython.lltypesystem import lltype from pypy.tool.udir import udir from pypy.rpython.test.test_llinterp import interpret, MallocMismatch +from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin from pypy.annotation.annrpython import RPythonAnnotator from pypy.rpython.rtyper import RPythonTyper from pypy.translator.backendopt.all import backend_optimizations @@ -437,6 +439,50 @@ unregister_keepalive(pos, TP) assert res == 8 + def test_nonmoving(self): + d = 'non-moving data stuff' + def f(): + raw_buf, gc_buf = alloc_buffer(len(d)) + try: + for i in range(len(d)): + raw_buf[i] = d[i] + return str_from_buffer(raw_buf, gc_buf, len(d), len(d)-1) + finally: + keep_buffer_alive_until_here(raw_buf, gc_buf) + fn = self.compile(f, [], gcpolicy='ref') + assert fn() == d[:-1] + + + def test_nonmovingbuffer(self): + d = 'some cool data that should not move' + def f(): + buf = get_nonmovingbuffer(d) + try: + counter = 0 + for i in range(len(d)): + if buf[i] == d[i]: + counter += 1 + return counter + finally: + free_nonmovingbuffer(d, buf) + fn = self.compile(f, [], gcpolicy='ref') + assert fn() == len(d) + + def test_nonmovingbuffer_semispace(self): + d = 'some cool data that should not move' + def f(): + buf = get_nonmovingbuffer(d) + try: + counter = 0 + for i in range(len(d)): + if buf[i] == d[i]: + counter += 1 + return counter + finally: + free_nonmovingbuffer(d, buf) + fn = self.compile(f, [], gcpolicy='semispace') + assert fn(expected_extra_mallocs=9) == len(d) + class TestRffiInternals: def test_struct_create(self): X = CStruct('xx', ('one', INT)) @@ -501,8 +547,7 @@ graph = graphof(a.translator, f) s = summary(graph) # there should be not too many operations here by now - expected = {'cast_int_to_uint': 1, 'direct_call': 1, - 'cast_primitive': 2, 'cast_int_to_float': 1} + expected = {'force_cast': 3, 'cast_int_to_float': 1, 'direct_call': 1} for k, v in expected.items(): assert s[k] == v @@ -656,7 +701,6 @@ def test_ptradd_interpret(): interpret(test_ptradd, []) - class TestCRffi(BaseTestRffi): def compile(self, func, args, **kwds): return compile_c(func, args, **kwds) @@ -672,6 +716,14 @@ del kwds['backendopt'] return compile_llvm(func, args, **kwds) + def test_nonmovingbuffer(self): + py.test.skip("Somewhat buggy...") + + test_nonmoving = test_nonmovingbuffer + + def test_nonmovingbuffer_semispace(self): + py.test.skip("LLVM backend error - unsupported operator") + def test_hashdefine(self): py.test.skip("Macros cannot be called as llexternals by design, rffi does not have any special support for them") Modified: pypy/dist/pypy/rpython/memory/gc/base.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gc/base.py (original) +++ pypy/dist/pypy/rpython/memory/gc/base.py Wed May 21 16:04:51 2008 @@ -7,6 +7,7 @@ needs_write_barrier = False malloc_zero_filled = False prebuilt_gc_objects_are_static_roots = True + can_realloc = False # The following flag enables costly consistency checks after each # collection. It is automatically set to True by test_gc.py. The @@ -50,16 +51,13 @@ def size_gc_header(self, typeid=0): return self.gcheaderbuilder.size_gc_header - def malloc(self, typeid, length=0, zero=False, coallocator=None): + def malloc(self, typeid, length=0, zero=False): """For testing. The interface used by the gctransformer is the four malloc_[fixed,var]size[_clear]() functions. - And (if they exist) to the coalloc_[fixed,var]size_clear functions """ # Rules about fallbacks in case of missing malloc methods: # * malloc_fixedsize_clear() and malloc_varsize_clear() are mandatory # * malloc_fixedsize() and malloc_varsize() fallback to the above - # * coalloc_fixedsize_clear() and coalloc_varsize_clear() are optional - # There is no non-clear version of coalloc for now. # XXX: as of r49360, gctransformer.framework never inserts calls # to malloc_varsize(), but always uses malloc_varsize_clear() @@ -71,39 +69,28 @@ assert not contains_weakptr itemsize = self.varsize_item_sizes(typeid) offset_to_length = self.varsize_offset_to_length(typeid) - if (coallocator is not None and - hasattr(self, "coalloc_varsize_clear")): - assert not needs_finalizer - coallocator = llmemory.cast_ptr_to_adr(coallocator) - ref = self.coalloc_varsize_clear(coallocator, typeid, - length, size, - itemsize, offset_to_length) + if zero or not hasattr(self, 'malloc_varsize'): + malloc_varsize = self.malloc_varsize_clear else: - if zero or not hasattr(self, 'malloc_varsize'): - malloc_varsize = self.malloc_varsize_clear - else: - malloc_varsize = self.malloc_varsize - ref = malloc_varsize(typeid, length, size, itemsize, - offset_to_length, True, needs_finalizer) + malloc_varsize = self.malloc_varsize + ref = malloc_varsize(typeid, length, size, itemsize, + offset_to_length, True, needs_finalizer) else: - if (coallocator is not None and - hasattr(self, "coalloc_fixedsize_clear")): - assert not needs_finalizer - coallocator = llmemory.cast_ptr_to_adr(coallocator) - ref = self.coalloc_fixedsize_clear(coallocator, typeid, size) + if zero or not hasattr(self, 'malloc_fixedsize'): + malloc_fixedsize = self.malloc_fixedsize_clear else: - if zero or not hasattr(self, 'malloc_fixedsize'): - malloc_fixedsize = self.malloc_fixedsize_clear - else: - malloc_fixedsize = self.malloc_fixedsize - ref = malloc_fixedsize(typeid, size, True, needs_finalizer, - contains_weakptr) + malloc_fixedsize = self.malloc_fixedsize + ref = malloc_fixedsize(typeid, size, True, needs_finalizer, + contains_weakptr) # lots of cast and reverse-cast around... return llmemory.cast_ptr_to_adr(ref) def id(self, ptr): return lltype.cast_ptr_to_int(ptr) + def can_move(self, addr): + return False + def set_max_heap_size(self, size): pass @@ -198,6 +185,8 @@ class MovingGCBase(GCBase): moving_gc = True + def can_move(self, addr): + return True def choose_gc_from_config(config): """Return a (GCClass, GC_PARAMS) from the given config object. Modified: pypy/dist/pypy/rpython/memory/gc/generation.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gc/generation.py (original) +++ pypy/dist/pypy/rpython/memory/gc/generation.py Wed May 21 16:04:51 2008 @@ -158,18 +158,6 @@ self.young_objects_with_weakrefs.append(result + size_gc_header) return llmemory.cast_adr_to_ptr(result+size_gc_header, llmemory.GCREF) - def coalloc_fixedsize_clear(self, coallocator, typeid, size): - # note: a coallocated object can never return a weakref, since the - # coallocation analysis is done at a time where weakrefs are - # represented as opaque objects which aren't allocated using malloc but - # with weakref_create - if self.is_in_nursery(coallocator): - return self.malloc_fixedsize_clear(typeid, size, - True, False, False) - else: - return SemiSpaceGC.malloc_fixedsize_clear(self, typeid, size, - True, False, False) - def malloc_varsize_clear(self, typeid, length, size, itemsize, offset_to_length, can_collect, has_finalizer=False): @@ -217,17 +205,6 @@ self.nursery_free = result + llarena.round_up_for_allocation(totalsize) return llmemory.cast_adr_to_ptr(result+size_gc_header, llmemory.GCREF) - def coalloc_varsize_clear(self, coallocator, typeid, - length, size, itemsize, - offset_to_length): - if self.is_in_nursery(coallocator): - return self.malloc_varsize_clear(typeid, length, size, itemsize, - offset_to_length, True, False) - else: - return SemiSpaceGC.malloc_varsize_clear(self, typeid, length, size, - itemsize, offset_to_length, - True, False) - # override the init_gc_object methods to change the default value of 'flags', # used by objects that are directly created outside the nursery by the SemiSpaceGC. # These objects must have the GCFLAG_NO_YOUNG_PTRS flag set immediately. Modified: pypy/dist/pypy/rpython/memory/gctransform/boehm.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gctransform/boehm.py (original) +++ pypy/dist/pypy/rpython/memory/gctransform/boehm.py Wed May 21 16:04:51 2008 @@ -4,6 +4,8 @@ from pypy.rpython.lltypesystem import lltype, llmemory from pypy.objspace.flow.model import Constant from pypy.rpython.lltypesystem.lloperation import llop +from pypy.rpython.lltypesystem import rffi +from pypy.rpython import rmodel class BoehmGCTransformer(GCTransformer): malloc_zero_filled = True @@ -19,12 +21,19 @@ mh = mallocHelpers() mh.allocate = lambda size: llop.boehm_malloc(llmemory.Address, size) + c_realloc = rffi.llexternal('GC_REALLOC', [rffi.VOIDP, rffi.INT], + rffi.VOIDP) + def _realloc(ptr, size): + return llmemory.cast_ptr_to_adr(c_realloc(rffi.cast(rffi.VOIDP, ptr), size)) + mh.realloc = _realloc ll_malloc_fixedsize = mh._ll_malloc_fixedsize # XXX, do we need/want an atomic version of this function? ll_malloc_varsize_no_length = mh.ll_malloc_varsize_no_length ll_malloc_varsize = mh.ll_malloc_varsize + ll_realloc = mh.ll_realloc + if self.translator: self.malloc_fixedsize_ptr = self.inittime_helper( ll_malloc_fixedsize, [lltype.Signed], llmemory.Address) @@ -39,6 +48,9 @@ inline=False) self.weakref_deref_ptr = self.inittime_helper( ll_weakref_deref, [llmemory.WeakRefPtr], llmemory.Address) + self.realloc_ptr = self.inittime_helper( + ll_realloc, [llmemory.Address] + [lltype.Signed] * 4, + llmemory.Address) self.mixlevelannotator.finish() # for now self.mixlevelannotator.backend_optimize() @@ -48,6 +60,15 @@ def pop_alive_nopyobj(self, var, llops): pass + def _can_realloc(self): + return True + + def perform_realloc(self, hop, v_ptr, v_newlgt, c_const_size, c_item_size, + c_lengthofs): + args = [self.realloc_ptr, v_ptr, v_newlgt, c_const_size, + c_item_size, c_lengthofs] + return hop.genop('direct_call', args, resulttype=llmemory.Address) + def gct_fv_gc_malloc(self, hop, flags, TYPE, c_size): # XXX same behavior for zero=True: in theory that's wrong if TYPE._is_atomic(): @@ -63,7 +84,6 @@ hop.genop("boehm_register_finalizer", [v_raw, c_finalizer_ptr]) return v_raw - def gct_fv_gc_malloc_varsize(self, hop, flags, TYPE, v_length, c_const_size, c_item_size, c_offset_to_length): # XXX same behavior for zero=True: in theory that's wrong Modified: pypy/dist/pypy/rpython/memory/gctransform/framework.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gctransform/framework.py (original) +++ pypy/dist/pypy/rpython/memory/gctransform/framework.py Wed May 21 16:04:51 2008 @@ -221,6 +221,9 @@ [s_gc], annmodel.s_None) self.enable_finalizers_ptr = getfn(GCClass.enable_finalizers.im_func, [s_gc], annmodel.s_None) + self.can_move_ptr = getfn(GCClass.can_move.im_func, + [s_gc, annmodel.SomeAddress()], + annmodel.SomeBool()) # in some GCs we can inline the common case of # malloc_fixedsize(typeid, size, True, False, False) @@ -292,20 +295,6 @@ inline=True) else: self.write_barrier_ptr = None - if hasattr(GCClass, "coalloc_fixedsize_clear"): - self.coalloc_clear_ptr = getfn( - GCClass.coalloc_fixedsize_clear.im_func, - [s_gc, annmodel.SomeAddress(), - annmodel.SomeInteger(nonneg=True), - annmodel.SomeInteger(nonneg=True)], - s_gcref, inline=True) - self.coalloc_varsize_clear_ptr = getfn( - GCClass.coalloc_varsize_clear.im_func, - [s_gc, annmodel.SomeAddress()] + - [annmodel.SomeInteger(nonneg=True) for i in range(5)], - s_gcref, inline=True) - else: - self.coalloc_clear_ptr = self.coalloc_varsize_clear_ptr = None self.statistics_ptr = getfn(GCClass.statistics.im_func, [s_gc, annmodel.SomeInteger()], annmodel.SomeInteger()) @@ -450,7 +439,7 @@ has_finalizer = bool(self.finalizer_funcptr_for_type(TYPE)) c_has_finalizer = rmodel.inputconst(lltype.Bool, has_finalizer) - if not op.opname.endswith('_varsize'): + if not op.opname.endswith('_varsize') and not flags.get('varsize'): #malloc_ptr = self.malloc_fixedsize_ptr zero = flags.get('zero', False) if (self.malloc_fast_ptr is not None and @@ -483,43 +472,6 @@ gct_fv_gc_malloc_varsize = gct_fv_gc_malloc - def gct_fv_gc_coalloc(self, hop, coallocator, flags, TYPE, *args): - if self.coalloc_clear_ptr is None: - return self.gct_fv_gc_malloc( - hop, flags, TYPE, *args) - op = hop.spaceop - flavor = flags['flavor'] - assert not flags.get("nocollect", False) - - PTRTYPE = op.result.concretetype - assert PTRTYPE.TO == TYPE - type_id = self.get_type_id(TYPE) - - c_type_id = rmodel.inputconst(lltype.Signed, type_id) - info = self.layoutbuilder.type_info_list[type_id] - c_size = rmodel.inputconst(lltype.Signed, info.fixedsize) - has_finalizer = bool(self.finalizer_funcptr_for_type(TYPE)) - assert not has_finalizer - - v_coallocator = gen_cast(hop.llops, llmemory.Address, coallocator) - - if not op.opname.endswith('_varsize'): - malloc_ptr = self.coalloc_clear_ptr - args = [self.c_const_gc, v_coallocator, c_type_id, c_size] - else: - v_length = op.args[-1] - c_ofstolength = rmodel.inputconst(lltype.Signed, info.ofstolength) - c_varitemsize = rmodel.inputconst(lltype.Signed, info.varitemsize) - malloc_ptr = self.coalloc_varsize_clear_ptr - args = [self.c_const_gc, v_coallocator, c_type_id, v_length, c_size, - c_varitemsize, c_ofstolength] - livevars = self.push_roots(hop) - v_result = hop.genop("direct_call", [malloc_ptr] + args, - resulttype=llmemory.GCREF) - self.pop_roots(hop, livevars) - return v_result - gct_fv_gc_coalloc_varsize = gct_fv_gc_coalloc - def gct_gc__collect(self, hop): op = hop.spaceop livevars = self.push_roots(hop) @@ -527,6 +479,16 @@ resultvar=op.result) self.pop_roots(hop, livevars) + def gct_gc_can_move(self, hop): + op = hop.spaceop + v_addr = hop.genop('cast_ptr_to_adr', + [op.args[0]], resulttype=llmemory.Address) + hop.genop("direct_call", [self.can_move_ptr, self.c_const_gc, v_addr], + resultvar=op.result) + + def _can_realloc(self): + return self.gcdata.gc.can_realloc + def gct_gc__disable_finalizers(self, hop): # cannot collect() op = hop.spaceop @@ -629,6 +591,22 @@ self.c_const_gc, v_size]) + def gct_malloc_nonmovable_varsize(self, hop): + TYPE = hop.spaceop.result.concretetype + if self.gcdata.gc.moving_gc: + # first approximation + c = rmodel.inputconst(TYPE, lltype.nullptr(TYPE.TO)) + return hop.cast_result(c) + return self.gct_malloc_varsize(hop) + + def gct_malloc_nonmovable(self, hop): + TYPE = hop.spaceop.result.concretetype + if self.gcdata.gc.moving_gc: + # first approximation + c = rmodel.inputconst(TYPE, lltype.nullptr(TYPE.TO)) + return hop.cast_result(c) + return self.gct_malloc(hop) + def transform_generic_set(self, hop): from pypy.objspace.flow.model import Constant opname = hop.spaceop.opname Modified: pypy/dist/pypy/rpython/memory/gctransform/transform.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gctransform/transform.py (original) +++ pypy/dist/pypy/rpython/memory/gctransform/transform.py Wed May 21 16:04:51 2008 @@ -455,6 +455,15 @@ return result mh.ll_malloc_varsize_no_length_zero = _ll_malloc_varsize_no_length_zero + def ll_realloc(ptr, length, constsize, itemsize, lengthoffset): + size = constsize + length * itemsize + result = mh.realloc(ptr, size) + if not result: + raise MemoryError() + (result + lengthoffset).signed[0] = length + return result + mh.ll_realloc = ll_realloc + return mh class GCTransformer(BaseGCTransformer): @@ -496,22 +505,7 @@ c_size = rmodel.inputconst(lltype.Signed, llmemory.sizeof(TYPE)) v_raw = meth(hop, flags, TYPE, c_size) hop.cast_result(v_raw) - - def gct_coalloc(self, hop): - TYPE = hop.spaceop.result.concretetype.TO - assert not TYPE._is_varsize() - flags = hop.spaceop.args[2].value - flavor = flags['flavor'] - c_size = rmodel.inputconst(lltype.Signed, llmemory.sizeof(TYPE)) - meth = getattr(self, 'gct_fv_%s_comalloc' % flavor, None) - if meth is None: - meth = getattr(self, 'gct_fv_%s_malloc' % flavor, None) - assert meth, "%s has no support for comalloc with flavor %r" % (self, flavor) - v_raw = meth(hop, flags, TYPE, c_size) - else: - v_raw = meth(hop, hop.spaceop.args[1], flags, TYPE, c_size) - hop.cast_result(v_raw) - + def gct_fv_raw_malloc(self, hop, flags, TYPE, c_size): v_raw = hop.genop("direct_call", [self.raw_malloc_fixedsize_ptr, c_size], resulttype=llmemory.Address) @@ -535,19 +529,79 @@ assert meth, "%s has no support for malloc_varsize with flavor %r" % (self, flavor) return self.varsize_malloc_helper(hop, flags, meth, []) - def gct_coalloc_varsize(self, hop): + gct_malloc_nonmovable = gct_malloc + gct_malloc_nonmovable_varsize = gct_malloc_varsize - flags = hop.spaceop.args[2].value + def gct_malloc_resizable_buffer(self, hop): + flags = hop.spaceop.args[1].value + flags['varsize'] = True flavor = flags['flavor'] - meth = getattr(self, 'gct_fv_%s_coalloc_varsize' % flavor, None) - if meth is None: - meth = getattr(self, 'gct_fv_%s_malloc_varsize' % flavor, None) - assert meth, "%s has no support for malloc_varsize with flavor %r" % (self, flavor) - return self.varsize_malloc_helper(hop, flags, meth, []) + assert flavor != 'cpy', "cannot malloc CPython objects directly" + meth = getattr(self, 'gct_fv_%s_malloc_varsize' % flavor, None) + assert meth, "%s has no support for malloc_varsize with flavor %r" % (self, flavor) + return self.varsize_malloc_helper(hop, flags, meth, []) + + def gct_resize_buffer(self, hop): + op = hop.spaceop + if self._can_realloc(): + self._gct_resize_buffer_realloc(hop, op.args[2]) else: - return self.varsize_malloc_helper(hop, flags, meth, - [hop.spaceop.args[1]]) + self._gct_resize_buffer_no_realloc(hop, op.args[1]) + def _can_realloc(self): + return False + + def _gct_resize_buffer_realloc(self, hop, v_newsize): + def intconst(c): return rmodel.inputconst(lltype.Signed, c) + op = hop.spaceop + flags = {'flavor':'gc', 'varsize': True} + TYPE = op.args[0].concretetype.TO + ARRAY = TYPE._flds[TYPE._arrayfld] + offset_to_length = llmemory.FieldOffset(TYPE, TYPE._arrayfld) + \ + llmemory.ArrayLengthOffset(ARRAY) + c_const_size = intconst(llmemory.sizeof(TYPE, 0)) + c_item_size = intconst(llmemory.sizeof(ARRAY.OF)) + + c_lengthofs = intconst(offset_to_length) + v_ptr = op.args[0] + v_raw = self.perform_realloc(hop, v_ptr, v_newsize, c_const_size, + c_item_size, c_lengthofs) + hop.cast_result(v_raw) + + def _gct_resize_buffer_no_realloc(self, hop, v_lgt): + op = hop.spaceop + meth = self.gct_fv_gc_malloc_varsize + flags = {'flavor':'gc', 'varsize': True} + self.varsize_malloc_helper(hop, flags, meth, []) + # fish resvar + v_newbuf = hop.llops[-1].result + v_src = op.args[0] + TYPE = v_src.concretetype.TO + c_fldname = rmodel.inputconst(lltype.Void, TYPE._arrayfld) + v_adrsrc = hop.genop('cast_ptr_to_adr', [v_src], + resulttype=llmemory.Address) + v_adrnewbuf = hop.genop('cast_ptr_to_adr', [v_newbuf], + resulttype=llmemory.Address) + ofs = (llmemory.offsetof(TYPE, TYPE._arrayfld) + + llmemory.itemoffsetof(getattr(TYPE, TYPE._arrayfld), 0)) + v_ofs = rmodel.inputconst(lltype.Signed, ofs) + v_adrsrc = hop.genop('adr_add', [v_adrsrc, v_ofs], + resulttype=llmemory.Address) + v_adrnewbuf = hop.genop('adr_add', [v_adrnewbuf, v_ofs], + resulttype=llmemory.Address) + size = llmemory.sizeof(getattr(TYPE, TYPE._arrayfld).OF) + c_size = rmodel.inputconst(lltype.Signed, size) + v_lgtsym = hop.genop('int_mul', [c_size, v_lgt], + resulttype=lltype.Signed) + vlist = [v_adrsrc, v_adrnewbuf, v_lgtsym] + hop.genop('raw_memcopy', vlist) + + def gct_finish_building_buffer(self, hop): + op = hop.spaceop + if self._can_realloc(): + return self._gct_resize_buffer_realloc(hop, op.args[1]) + else: + return self._gct_resize_buffer_no_realloc(hop, op.args[1]) def varsize_malloc_helper(self, hop, flags, meth, extraargs): def intconst(c): return rmodel.inputconst(lltype.Signed, c) @@ -575,10 +629,8 @@ args = [hop] + extraargs + [flags, TYPE, op.args[-1], c_const_size, c_item_size, c_offset_to_length] v_raw = meth(*args) - hop.cast_result(v_raw) - def gct_fv_raw_malloc_varsize(self, hop, flags, TYPE, v_length, c_const_size, c_item_size, c_offset_to_length): if c_offset_to_length is None: @@ -608,3 +660,6 @@ hop.genop('raw_free', [v]) else: assert False, "%s has no support for free with flavor %r" % (self, flavor) + + def gct_gc_can_move(self, hop): + return hop.cast_result(rmodel.inputconst(lltype.Bool, False)) Modified: pypy/dist/pypy/rpython/memory/gcwrapper.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gcwrapper.py (original) +++ pypy/dist/pypy/rpython/memory/gcwrapper.py Wed May 21 16:04:51 2008 @@ -44,21 +44,42 @@ else: return lltype.malloc(TYPE, n, flavor=flavor, zero=zero) + def malloc_nonmovable(self, TYPE, n=None, zero=False): + typeid = self.get_type_id(TYPE) + if self.gc.moving_gc: + return lltype.nullptr(TYPE) + addr = self.gc.malloc(typeid, n, zero=zero) + result = llmemory.cast_adr_to_ptr(addr, lltype.Ptr(TYPE)) + if not self.gc.malloc_zero_filled: + gctypelayout.zero_gc_pointers(result) + return result + + def malloc_resizable_buffer(self, TYPE, n): + typeid = self.get_type_id(TYPE) + addr = self.gc.malloc(typeid, n) + result = llmemory.cast_adr_to_ptr(addr, lltype.Ptr(TYPE)) + if not self.gc.malloc_zero_filled: + gctypelayout.zero_gc_pointers(result) + return result + + def resize_buffer(self, obj, old_size, new_size): + T = lltype.typeOf(obj).TO + buf = self.malloc_resizable_buffer(T, new_size) + # copy contents + arrayfld = T._arrayfld + new_arr = getattr(buf, arrayfld) + old_arr = getattr(obj, arrayfld) + for i in range(old_size): + new_arr[i] = old_arr[i] + return buf + + def finish_building_buffer(self, obj, size): + return obj + def free(self, TYPE, flavor='gc'): assert flavor != 'gc' return lltype.free(TYPE, flavor=flavor) - def coalloc(self, TYPE, coallocator, size=None, zero=False): - if hasattr(self.gc, "coalloc_fixedsize_clear"): - typeid = self.get_type_id(TYPE) - addr = self.gc.malloc(typeid, size, zero=zero, - coallocator=coallocator) - result = llmemory.cast_adr_to_ptr(addr, lltype.Ptr(TYPE)) - if not self.gc.malloc_zero_filled: - gctypelayout.zero_gc_pointers(result) - return result - return self.malloc(TYPE, size, 'gc', zero) - def setfield(self, obj, fieldname, fieldvalue): STRUCT = lltype.typeOf(obj).TO addr = llmemory.cast_ptr_to_adr(obj) @@ -89,6 +110,9 @@ def enable_finalizers(self): self.gc.enable_finalizers() + def can_move(self, addr): + return self.gc.can_move(addr) + def weakref_create_getlazy(self, objgetter): # we have to be lazy in reading the llinterp variable containing # the 'obj' pointer, because the gc.malloc() call below could Modified: pypy/dist/pypy/rpython/memory/test/test_gc.py ============================================================================== --- pypy/dist/pypy/rpython/memory/test/test_gc.py (original) +++ pypy/dist/pypy/rpython/memory/test/test_gc.py Wed May 21 16:04:51 2008 @@ -21,6 +21,7 @@ class GCTest(object): GC_PARAMS = {} + GC_CAN_MOVE = False def setup_class(cls): cls._saved_logstate = py.log._getstate() @@ -388,12 +389,66 @@ res = self.interpret(f, []) assert res == 42 + def test_can_move(self): + TP = lltype.GcArray(lltype.Float) + def func(): + from pypy.rlib import rgc + return rgc.can_move(lltype.malloc(TP, 1)) + assert self.interpret(func, []) == self.GC_CAN_MOVE + + + def test_malloc_nonmovable(self): + TP = lltype.GcArray(lltype.Char) + def func(): + try: + from pypy.rlib import rgc + a = rgc.malloc_nonmovable(TP, 3) + if a: + assert not rgc.can_move(a) + return 0 + return 1 + except Exception, e: + return 2 + + assert self.interpret(func, []) == int(self.GC_CAN_MOVE) + + def test_malloc_nonmovable_fixsize(self): + S = lltype.GcStruct('S', ('x', lltype.Float)) + TP = lltype.GcStruct('T', ('s', lltype.Ptr(S))) + def func(): + try: + from pypy.rlib import rgc + a = rgc.malloc_nonmovable(TP) + rgc.collect() + if a: + assert not rgc.can_move(a) + return 0 + return 1 + except Exception, e: + return 2 + + assert self.interpret(func, []) == int(self.GC_CAN_MOVE) + + def test_resizable_buffer(self): + from pypy.rpython.lltypesystem.rstr import STR + from pypy.rpython.annlowlevel import hlstr + from pypy.rlib import rgc + + def f(): + ptr = rgc.resizable_buffer_of_shape(STR, 1) + ptr.chars[0] = 'a' + ptr = rgc.resize_buffer(ptr, 1, 2) + ptr.chars[1] = 'b' + return len(hlstr(rgc.finish_building_buffer(ptr, 2))) + + assert self.interpret(f, []) == 2 class TestMarkSweepGC(GCTest): from pypy.rpython.memory.gc.marksweep import MarkSweepGC as GCClass class TestSemiSpaceGC(GCTest, snippet.SemiSpaceGCTests): from pypy.rpython.memory.gc.semispace import SemiSpaceGC as GCClass + GC_CAN_MOVE = True class TestGrowingSemiSpaceGC(TestSemiSpaceGC): GC_PARAMS = {'space_size': 64} @@ -401,20 +456,6 @@ class TestGenerationalGC(TestSemiSpaceGC): from pypy.rpython.memory.gc.generation import GenerationGC as GCClass - def test_coalloc(self): - def malloc_a_lot(): - i = 0 - while i < 10: - i += 1 - a = [1] * 10 - j = 0 - while j < 30: - j += 1 - a.append(j) - return 0 - res = self.interpret(malloc_a_lot, [], backendopt=True, coalloc=True) - assert res == 0 - class TestHybridGC(TestGenerationalGC): from pypy.rpython.memory.gc.hybrid import HybridGC as GCClass Modified: pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py ============================================================================== --- pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py (original) +++ pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py Wed May 21 16:04:51 2008 @@ -36,6 +36,7 @@ class GCTest(object): gcpolicy = None stacklessgc = False + GC_CAN_MOVE = False def runner(self, f, nbargs=0, statistics=False, transformer=False, **extraconfigopts): @@ -446,8 +447,68 @@ res = run([]) assert res == 0 + def test_can_move(self): + TP = lltype.GcArray(lltype.Float) + def func(): + from pypy.rlib import rgc + return rgc.can_move(lltype.malloc(TP, 1)) + run = self.runner(func) + res = run([]) + assert res == self.GC_CAN_MOVE + + def test_malloc_nonmovable(self): + TP = lltype.GcArray(lltype.Char) + def func(): + try: + from pypy.rlib import rgc + a = rgc.malloc_nonmovable(TP, 3) + rgc.collect() + if a: + assert not rgc.can_move(a) + return 0 + return 1 + except Exception, e: + return 2 + + run = self.runner(func) + assert int(self.GC_CAN_MOVE) == run([]) + + def test_malloc_nonmovable_fixsize(self): + S = lltype.GcStruct('S', ('x', lltype.Float)) + TP = lltype.GcStruct('T', ('s', lltype.Ptr(S))) + def func(): + try: + from pypy.rlib import rgc + a = rgc.malloc_nonmovable(TP) + rgc.collect() + if a: + assert not rgc.can_move(a) + return 0 + return 1 + except Exception, e: + return 2 + + run = self.runner(func) + assert run([]) == int(self.GC_CAN_MOVE) + + def test_resizable_buffer(self): + from pypy.rpython.lltypesystem.rstr import STR + from pypy.rpython.annlowlevel import hlstr + from pypy.rlib import rgc + + def f(): + ptr = rgc.resizable_buffer_of_shape(STR, 2) + ptr.chars[0] = 'a' + ptr = rgc.resize_buffer(ptr, 1, 200) + ptr.chars[1] = 'b' + return hlstr(rgc.finish_building_buffer(ptr, 2)) == "ab" + + run = self.runner(f) + assert run([]) == 1 class GenericMovingGCTests(GenericGCTests): + GC_CAN_MOVE = True + def test_many_ids(self): py.test.skip("fails for bad reasons in lltype.py :-(") class A(object): @@ -476,7 +537,6 @@ run = self.runner(f) run([]) - class TestMarkSweepGC(GenericGCTests): gcname = "marksweep" class gcpolicy(gc.FrameworkGcPolicy): @@ -699,21 +759,6 @@ res = run([3, 0]) assert res == 1 - def test_coalloc(self): - def malloc_a_lot(): - i = 0 - while i < 10: - i += 1 - a = [1] * 10 - j = 0 - while j < 30: - j += 1 - a.append(j) - return 0 - run, statistics = self.runner(malloc_a_lot, statistics=True, - backendopt=True, coalloc=True) - run([]) - class TestPrintingGC(GenericGCTests): gcname = "statistics" Modified: pypy/dist/pypy/rpython/module/ll_os.py ============================================================================== --- pypy/dist/pypy/rpython/module/ll_os.py (original) +++ pypy/dist/pypy/rpython/module/ll_os.py Wed May 21 16:04:51 2008 @@ -20,10 +20,13 @@ from pypy.tool.udir import udir from pypy.translator.tool.cbuild import ExternalCompilationInfo from pypy.rpython.lltypesystem.rstr import mallocstr -from pypy.rpython.annlowlevel import hlstr -from pypy.rpython.lltypesystem.llmemory import raw_memcopy, sizeof,\ - itemoffsetof, cast_ptr_to_adr, offsetof +from pypy.rpython.annlowlevel import llstr +from pypy.rpython.lltypesystem.llmemory import sizeof,\ + itemoffsetof, cast_ptr_to_adr, cast_adr_to_ptr, offsetof from pypy.rpython.lltypesystem.rstr import STR +from pypy.rpython.annlowlevel import llstr +from pypy.rlib import rgc +from pypy.rlib.objectmodel import keepalive_until_here posix = __import__(os.name) @@ -484,20 +487,16 @@ def os_read_llimpl(fd, count): if count < 0: raise OSError(errno.EINVAL, None) - inbuf = lltype.malloc(rffi.CCHARP.TO, count, flavor='raw') + raw_buf, gc_buf = rffi.alloc_buffer(count) try: - got = rffi.cast(lltype.Signed, os_read(fd, inbuf, count)) + void_buf = rffi.cast(rffi.VOIDP, raw_buf) + got = rffi.cast(lltype.Signed, os_read(fd, void_buf, count)) if got < 0: raise OSError(rposix.get_errno(), "os_read failed") - s = mallocstr(got) - source = cast_ptr_to_adr(inbuf) + \ - itemoffsetof(lltype.typeOf(inbuf).TO, 0) - dest = cast_ptr_to_adr(s) + offset - raw_memcopy(source, dest, sizeof(lltype.Char) * got) + return rffi.str_from_buffer(raw_buf, gc_buf, count, got) finally: - lltype.free(inbuf, flavor='raw') - return hlstr(s) - + rffi.keep_buffer_alive_until_here(raw_buf, gc_buf) + def os_read_oofakeimpl(fd, count): return OOSupport.to_rstr(os.read(fd, count)) @@ -512,17 +511,15 @@ def os_write_llimpl(fd, data): count = len(data) - outbuf = lltype.malloc(rffi.CCHARP.TO, count, flavor='raw') + buf = rffi.get_nonmovingbuffer(data) try: - for i in range(count): - outbuf[i] = data[i] written = rffi.cast(lltype.Signed, os_write( rffi.cast(rffi.INT, fd), - outbuf, rffi.cast(rffi.SIZE_T, count))) + buf, rffi.cast(rffi.SIZE_T, count))) if written < 0: raise OSError(rposix.get_errno(), "os_write failed") finally: - lltype.free(outbuf, flavor='raw') + rffi.free_nonmovingbuffer(data, buf) return written def os_write_oofakeimpl(fd, data): Modified: pypy/dist/pypy/rpython/module/test/test_posix.py ============================================================================== --- pypy/dist/pypy/rpython/module/test/test_posix.py (original) +++ pypy/dist/pypy/rpython/module/test/test_posix.py Wed May 21 16:04:51 2008 @@ -72,7 +72,10 @@ def test_write(self): def f(fi): - text = 'This is a test' + if fi > 0: + text = 'This is a test' + else: + text = '333' return posix.write(fi,text) fi = os.open(path,os.O_WRONLY,0777) text = 'This is a test' Modified: pypy/dist/pypy/rpython/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/rpbc.py (original) +++ pypy/dist/pypy/rpython/rpbc.py Wed May 21 16:04:51 2008 @@ -11,6 +11,7 @@ mangle, inputdesc, warning, impossible_repr from pypy.rpython import rclass from pypy.rpython import robject +from pypy.rpython.annlowlevel import llstr from pypy.rpython import callparse @@ -605,6 +606,9 @@ def none_call(self, hop): raise TyperError("attempt to call constant None") + def ll_str(self, none): + return llstr("None") + rtype_simple_call = none_call rtype_call_args = none_call Modified: pypy/dist/pypy/rpython/test/test_annlowlevel.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_annlowlevel.py (original) +++ pypy/dist/pypy/rpython/test/test_annlowlevel.py Wed May 21 16:04:51 2008 @@ -4,7 +4,7 @@ from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin from pypy.rpython.lltypesystem.rstr import mallocstr -from pypy.rpython.annlowlevel import hlstr +from pypy.rpython.annlowlevel import hlstr, llstr class TestLLType(BaseRtypingTest, LLRtypeMixin): def test_hlstr(self): @@ -13,4 +13,19 @@ s.chars[1] = "b" s.chars[2] = "c" assert hlstr(s) == "abc" + + def test_llstr(self): + s = llstr("abc") + assert len(s.chars) == 3 + assert s.chars[0] == "a" + assert s.chars[1] == "b" + assert s.chars[2] == "c" + + def test_llstr_compile(self): + def f(arg): + s = llstr(hlstr(arg)) + return len(s.chars) + + res = self.interpret(f, [self.string_to_ll("abc")]) + assert res == 3 Modified: pypy/dist/pypy/rpython/test/test_rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rbuiltin.py (original) +++ pypy/dist/pypy/rpython/test/test_rbuiltin.py Wed May 21 16:04:51 2008 @@ -221,10 +221,10 @@ f = file(tmpfile, 'w') f.write('hello world') f.close() - def f(): + def fn(): fd = os.open(tmpfile, os.O_RDONLY, 0777) return os.read(fd, 4096) - res = self.interpret(f, []) + res = self.interpret(fn, []) assert self.ll_to_string(res) == 'hello world' def test_os_lseek(self): Modified: pypy/dist/pypy/rpython/test/test_rlist.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rlist.py (original) +++ pypy/dist/pypy/rpython/test/test_rlist.py Wed May 21 16:04:51 2008 @@ -730,6 +730,12 @@ res = self.interpret(fn, []) assert self.ll_to_string(res) == fn() + def fn(): + return str([1.25]) + + res = self.interpret(fn, []) + assert eval(self.ll_to_string(res)) == [1.25] + def test_list_or_None(self): empty_list = [] nonempty_list = [1, 2] Modified: pypy/dist/pypy/rpython/test/test_runicode.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_runicode.py (original) +++ pypy/dist/pypy/rpython/test/test_runicode.py Wed May 21 16:04:51 2008 @@ -211,10 +211,6 @@ test_float = unsupported test_hlstr = unsupported - def test_find_empty_string(self): - py.test.skip("We should think how to solve this problem") - test_rfind_empty_string = test_find_empty_string - class TestLLtype(BaseTestRUnicode, LLRtypeMixin): EMPTY_STRING_HASH = -1 Modified: pypy/dist/pypy/rpython/typesystem.py ============================================================================== --- pypy/dist/pypy/rpython/typesystem.py (original) +++ pypy/dist/pypy/rpython/typesystem.py Wed May 21 16:04:51 2008 @@ -22,7 +22,7 @@ return None if name in ('rclass', 'rpbc', 'rbuiltin', 'rtuple', 'rlist', 'rslice', 'rdict', 'rrange', 'rstr', 'rgeneric', - 'll_str', 'exceptiondata'): + 'll_str', 'rbuilder', 'exceptiondata'): mod = load(name) if mod is not None: setattr(self, name, mod) Modified: pypy/dist/pypy/translator/backendopt/all.py ============================================================================== --- pypy/dist/pypy/translator/backendopt/all.py (original) +++ pypy/dist/pypy/translator/backendopt/all.py Wed May 21 16:04:51 2008 @@ -130,10 +130,6 @@ print "after if-to-switch:" print_statistics(translator.graphs[0], translator) - if config.coalloc and not secondary: - from pypy.translator.backendopt import coalloc - coalloc.malloc_to_coalloc(translator) - remove_obvious_noops() for graph in graphs: Modified: pypy/dist/pypy/translator/c/funcgen.py ============================================================================== --- pypy/dist/pypy/translator/c/funcgen.py (original) +++ pypy/dist/pypy/translator/c/funcgen.py Wed May 21 16:04:51 2008 @@ -699,6 +699,8 @@ typename = cdecl(self.db.gettype(TYPE), '') return "%(result)s = (%(typename)s)(%(val)s);" % locals() + OP_FORCE_CAST = OP_CAST_PRIMITIVE # xxx the same logic works + def OP_RESUME_POINT(self, op): return '/* resume point %s */'%(op.args[0],) Modified: pypy/dist/pypy/translator/c/test/test_boehm.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_boehm.py (original) +++ pypy/dist/pypy/translator/c/test/test_boehm.py Wed May 21 16:04:51 2008 @@ -367,6 +367,31 @@ res = c_fn(10000) assert res == 0 + def test_can_move(self): + from pypy.rlib import rgc + class A: + pass + def fn(): + return rgc.can_move(A()) + + c_fn = self.getcompiled(fn, []) + assert c_fn() == False + + def test_resizable_buffer(self): + from pypy.rpython.lltypesystem.rstr import STR + from pypy.rpython.annlowlevel import hlstr + from pypy.rlib import rgc + + def f(): + ptr = rgc.resizable_buffer_of_shape(STR, 2) + ptr.chars[0] = 'a' + ptr = rgc.resize_buffer(ptr, 1, 200) + ptr.chars[1] = 'b' + return hlstr(rgc.finish_building_buffer(ptr, 2)) == "ab" + + run = self.getcompiled(f) + assert run() == True + # reusing some tests from pypy.rpython.memory.test.snippet large_tests_ok = True Modified: pypy/dist/pypy/translator/c/test/test_lltyped.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_lltyped.py (original) +++ pypy/dist/pypy/translator/c/test/test_lltyped.py Wed May 21 16:04:51 2008 @@ -304,6 +304,23 @@ res = fn(100) assert res == 100 + len(list(names)) + def test_force_cast(self): + from pypy.rpython.annlowlevel import llstr + from pypy.rpython.lltypesystem.rstr import STR + from pypy.rpython.lltypesystem import rffi, llmemory, lltype + P = lltype.Ptr(lltype.FixedSizeArray(lltype.Char, 1)) + + def f(): + a = llstr("xyz") + b = (llmemory.cast_ptr_to_adr(a) + llmemory.offsetof(STR, 'chars') + + llmemory.itemoffsetof(STR.chars, 0)) + buf = rffi.cast(rffi.VOIDP, b) + return buf[2] + + fn = self.getcompiled(f, []) + res = fn() + assert res == 'z' + def test_array_nolength(self): A = Array(Signed, hints={'nolength': True}) a1 = malloc(A, 3, immortal=True) Modified: pypy/dist/pypy/translator/c/test/test_newgc.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_newgc.py (original) +++ pypy/dist/pypy/translator/c/test/test_newgc.py Wed May 21 16:04:51 2008 @@ -2,6 +2,7 @@ import sys import py from py.test import raises +import os from pypy.objspace.flow.model import summary from pypy.translator.translator import TranslationContext @@ -12,6 +13,7 @@ from pypy.rpython.memory.test import snippet from pypy.rlib.objectmodel import keepalive_until_here from pypy import conftest +from pypy.tool.udir import udir def compile_func(fn, inputtypes, t=None, gcpolicy="ref"): from pypy.config.pypyoption import get_pypy_config @@ -814,6 +816,25 @@ c_fn = self.getcompiled(f) assert c_fn() == 0 + def test_open_read_write_seek_close(self): + filename = str(udir.join('test_open_read_write_close.txt')) + def does_stuff(): + fd = os.open(filename, os.O_WRONLY | os.O_CREAT, 0777) + count = os.write(fd, "hello world\n") + assert count == len("hello world\n") + os.close(fd) + fd = os.open(filename, os.O_RDONLY, 0777) + result = os.lseek(fd, 1, 0) + assert result == 1 + data = os.read(fd, 500) + assert data == "ello world\n" + os.close(fd) + + f1 = self.getcompiled(does_stuff) + f1() + assert open(filename, 'r').read() == "hello world\n" + os.unlink(filename) + def test_callback_with_collect(self): from pypy.rlib.libffi import ffi_type_pointer, cast_type_to_ffitype,\ CDLL, ffi_type_void, CallbackFuncPtr, ffi_type_sint @@ -918,7 +939,6 @@ res = c_fn() assert res == 2 - class TestGenerationalGC(TestSemiSpaceGC): gcpolicy = "generation" should_be_moving = True Modified: pypy/dist/pypy/translator/exceptiontransform.py ============================================================================== --- pypy/dist/pypy/translator/exceptiontransform.py (original) +++ pypy/dist/pypy/translator/exceptiontransform.py Wed May 21 16:04:51 2008 @@ -346,7 +346,10 @@ block.recloseblock(l0, l) insert_zeroing_op = False - if spaceop.opname == 'malloc': + # XXX this is not right. it also inserts zero_gc_pointers_inside + # XXX on a path that malloc_nonmovable returns null, but does not raise + # XXX which might end up with a segfault. But we don't have such gc now + if spaceop.opname == 'malloc' or spaceop.opname == 'malloc_nonmovable': flavor = spaceop.args[1].value['flavor'] if flavor == 'gc': insert_zeroing_op = True Modified: pypy/dist/pypy/translator/llvm/opwriter.py ============================================================================== --- pypy/dist/pypy/translator/llvm/opwriter.py (original) +++ pypy/dist/pypy/translator/llvm/opwriter.py Wed May 21 16:04:51 2008 @@ -139,6 +139,8 @@ self.cast_int_to_ptr(opr) else: self.cast_primitive(opr) + elif op.opname == 'force_cast': + self.cast_primitive(opr) else: meth = getattr(self, op.opname, None) if not meth: From xoraxax at codespeak.net Wed May 21 16:14:41 2008 From: xoraxax at codespeak.net (xoraxax at codespeak.net) Date: Wed, 21 May 2008 16:14:41 +0200 (CEST) Subject: [pypy-svn] r55066 - in pypy/dist/pypy: tool translator/tool Message-ID: <20080521141441.430FF168428@codespeak.net> Author: xoraxax Date: Wed May 21 16:14:40 2008 New Revision: 55066 Modified: pypy/dist/pypy/tool/udir.py pypy/dist/pypy/translator/tool/cbuild.py Log: Fix copy&paste error.translator/tool/cbuild.py Modified: pypy/dist/pypy/tool/udir.py ============================================================================== --- pypy/dist/pypy/tool/udir.py (original) +++ pypy/dist/pypy/tool/udir.py Wed May 21 16:14:40 2008 @@ -24,4 +24,4 @@ except: basename = '-' -udir = local.make_numbered_dir(prefix='usession' + basename, keep=3) +udir = local.make_numbered_dir(prefix='usession' + basename, keep=300) Modified: pypy/dist/pypy/translator/tool/cbuild.py ============================================================================== --- pypy/dist/pypy/translator/tool/cbuild.py (original) +++ pypy/dist/pypy/translator/tool/cbuild.py Wed May 21 16:14:40 2008 @@ -66,7 +66,7 @@ compile_extra: list of parameters which will be directly passed to the compiler - compile_extra: list of parameters which will be directly passed to + link_extra: list of parameters which will be directly passed to the linker frameworks: list of Mac OS X frameworks which should passed to the From xoraxax at codespeak.net Wed May 21 16:18:34 2008 From: xoraxax at codespeak.net (xoraxax at codespeak.net) Date: Wed, 21 May 2008 16:18:34 +0200 (CEST) Subject: [pypy-svn] r55067 - pypy/dist/pypy/tool Message-ID: <20080521141834.47ED7168505@codespeak.net> Author: xoraxax Date: Wed May 21 16:18:33 2008 New Revision: 55067 Added: pypy/dist/pypy/tool/udir.py - copied unchanged from r53417, pypy/dist/pypy/tool/udir.py Log: One space was missing on the last command line, reverting checkin ... From antocuni at codespeak.net Wed May 21 16:23:21 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 21 May 2008 16:23:21 +0200 (CEST) Subject: [pypy-svn] r55068 - in pypy/dist/pypy/objspace/std: . test Message-ID: <20080521142321.DD73A168505@codespeak.net> Author: antocuni Date: Wed May 21 16:23:20 2008 New Revision: 55068 Modified: pypy/dist/pypy/objspace/std/dictobject.py pypy/dist/pypy/objspace/std/test/test_dictobject.py Log: (antocuni, hpk) make sure that dict.repr() doesn't call items() that could be overridden Modified: pypy/dist/pypy/objspace/std/dictobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/dictobject.py (original) +++ pypy/dist/pypy/objspace/std/dictobject.py Wed May 21 16:23:20 2008 @@ -202,7 +202,7 @@ # XXX for now, we cannot use iteritems() at app-level because # we want a reasonable result instead of a RuntimeError # even if the dict is mutated by the repr() in the loop. - for k, v in d.items(): + for k, v in dict.items(d): items.append(repr(k) + ": " + repr(v)) return "{" + ', '.join(items) + "}" finally: Modified: pypy/dist/pypy/objspace/std/test/test_dictobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/test/test_dictobject.py (original) +++ pypy/dist/pypy/objspace/std/test/test_dictobject.py Wed May 21 16:23:20 2008 @@ -362,10 +362,16 @@ d = D([('x', 'foo')], y = 'bar') assert d['x'] == 'foo' assert d['y'] == 'bar' + d.setdefault('z', 'baz') assert d['z'] == 'baz' + + d['foo'] = 'bar' + assert d['foo'] == 42 + d.update({'w': 'foobar'}) assert d['w'] == 'foobar' + d = d.copy() assert d['x'] == 'foo' @@ -373,6 +379,25 @@ assert d3['x'] == 42 assert d3['y'] == 42 + def test_overridden_setitem_customkey(self): + class D(dict): + def __setitem__(self, key, value): + dict.__setitem__(self, key, 42) + class Foo(object): + pass + + d = D() + key = Foo() + d[key] = 'bar' + assert d[key] == 42 + + def test_repr_with_overriden_items(self): + class D(dict): + def items(self): + return [] + + d = D([("foo", "foobar")]) + assert repr(d) == "{'foo': 'foobar'}" # the minimal 'space' needed to use a W_DictObject class FakeSpace: From tverwaes at codespeak.net Wed May 21 16:25:06 2008 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Wed, 21 May 2008 16:25:06 +0200 (CEST) Subject: [pypy-svn] r55069 - pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk Message-ID: <20080521142506.6C655168505@codespeak.net> Author: tverwaes Date: Wed May 21 16:25:05 2008 New Revision: 55069 Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py Log: adding fixes for warnings Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py Wed May 21 16:25:05 2008 @@ -128,13 +128,15 @@ self.guess_class_name() # read the methoddict - self.w_methoddict = w_self._fetch(constants.CLASS_METHODDICT_INDEX) - assert isinstance(self.w_methoddict, model.W_PointersObject) + w_methoddict = w_self._fetch(constants.CLASS_METHODDICT_INDEX) + assert isinstance(w_methoddict, model.W_PointersObject) + self.w_methoddict = w_methoddict w_superclass = w_self._fetch(constants.CLASS_SUPERCLASS_INDEX) if w_superclass.is_same_object(w_nil): self.w_superclass = None else: + assert isinstance(w_superclass, model.W_PointersObject) self.w_superclass = w_superclass def guess_class_name(self): @@ -315,6 +317,7 @@ from pypy.lang.smalltalk import objtable self._w_sender = objtable.w_nil self._stack = [] + self.currentBytecode = None AbstractRedirectingShadow.__init__(self, w_self) @staticmethod @@ -497,6 +500,9 @@ # XXX this is incorrect when there is subclassing return self._w_self_size + def tempframesize(self): + raise NotImplementedError() + class BlockContextShadow(ContextPartShadow): @staticmethod From tverwaes at codespeak.net Wed May 21 16:25:36 2008 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Wed, 21 May 2008 16:25:36 +0200 (CEST) Subject: [pypy-svn] r55070 - pypy/branch/smalltalk-shadow-changes/pypy/translator/goal Message-ID: <20080521142536.D776B168505@codespeak.net> Author: tverwaes Date: Wed May 21 16:25:35 2008 New Revision: 55070 Modified: pypy/branch/smalltalk-shadow-changes/pypy/translator/goal/targetfibsmalltalk.py pypy/branch/smalltalk-shadow-changes/pypy/translator/goal/targetimageloadingsmalltalk.py pypy/branch/smalltalk-shadow-changes/pypy/translator/goal/targettinybenchsmalltalk.py Log: checking in new versions of targets Modified: pypy/branch/smalltalk-shadow-changes/pypy/translator/goal/targetfibsmalltalk.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/translator/goal/targetfibsmalltalk.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/translator/goal/targetfibsmalltalk.py Wed May 21 16:25:35 2008 @@ -17,7 +17,7 @@ def build(): bytecode = ''.join(map(chr, [ 16, 119, 178, 154, 118, 164, 11, 112, 16, 118, 177, 224, 112, 16, 119, 177, 224, 176, 124 ])) shadow = mockclass(0).as_class_get_shadow() - method = model.W_CompiledMethod(1, bytecode, 1) + method = model.W_CompiledMethod(1, bytecode) method.literals = fakeliterals("fib:") shadow.installmethod("fib:", method) w_object = shadow.new() Modified: pypy/branch/smalltalk-shadow-changes/pypy/translator/goal/targetimageloadingsmalltalk.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/translator/goal/targetimageloadingsmalltalk.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/translator/goal/targetimageloadingsmalltalk.py Wed May 21 16:25:35 2008 @@ -10,32 +10,19 @@ mockclass = classtable.bootstrap_class -def new_interpreter(bytes): - assert isinstance(bytes, str) - w_method = model.W_CompiledMethod(0, bytes=bytes) - w_frame = w_method.create_frame(objtable.w_nil, []) - interp = interpreter.Interpreter() - interp.w_active_context = w_frame - return interp - - - def tinyBenchmarks(image): interp = interpreter.Interpreter() w_object = model.W_SmallInteger(0) # Should get this from w_object - w_smallint_class = image.special(constants.SO_SMALLINTEGER_CLASS) s_class = w_object.shadow_of_my_class() w_method = s_class.lookup("tinyBenchmarks") assert w_method w_frame = w_method.create_frame(w_object, []) - interp.w_active_context = w_frame + interp.store_w_active_context(w_frame) - print w_method - print "Going to execute %d toplevel bytecodes" % (len(w_method.bytes),) counter = 0 from pypy.lang.smalltalk.interpreter import BYTECODE_TABLE Modified: pypy/branch/smalltalk-shadow-changes/pypy/translator/goal/targettinybenchsmalltalk.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/translator/goal/targettinybenchsmalltalk.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/translator/goal/targettinybenchsmalltalk.py Wed May 21 16:25:35 2008 @@ -30,10 +30,8 @@ assert w_method w_frame = w_method.create_frame(w_object, []) - interp.w_active_context = w_frame + interp.store_w_active_context(w_frame) - print w_method - print "Going to execute %d toplevel bytecodes" % (len(w_method.bytes),) counter = 0 from pypy.lang.smalltalk.interpreter import BYTECODE_TABLE From fijal at codespeak.net Wed May 21 16:29:44 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 21 May 2008 16:29:44 +0200 (CEST) Subject: [pypy-svn] r55071 - pypy/dist/pypy/objspace/std Message-ID: <20080521142944.DE4CA168505@codespeak.net> Author: fijal Date: Wed May 21 16:29:44 2008 New Revision: 55071 Modified: pypy/dist/pypy/objspace/std/stringobject.py Log: Fix translation Modified: pypy/dist/pypy/objspace/std/stringobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/stringobject.py (original) +++ pypy/dist/pypy/objspace/std/stringobject.py Wed May 21 16:29:44 2008 @@ -861,7 +861,7 @@ def repr__String(space, w_str): s = w_str._value - buf = StringBuilder(len(s) + 10) + buf = StringBuilder(50) quote = "'" if quote in s and '"' not in s: From fijal at codespeak.net Wed May 21 17:12:20 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 21 May 2008 17:12:20 +0200 (CEST) Subject: [pypy-svn] r55072 - pypy/dist/pypy/translator/goal Message-ID: <20080521151220.66497168466@codespeak.net> Author: fijal Date: Wed May 21 17:12:18 2008 New Revision: 55072 Modified: pypy/dist/pypy/translator/goal/bench-cronjob.py Log: Remove the option from benchmark runs which was removed Modified: pypy/dist/pypy/translator/goal/bench-cronjob.py ============================================================================== --- pypy/dist/pypy/translator/goal/bench-cronjob.py (original) +++ pypy/dist/pypy/translator/goal/bench-cronjob.py Wed May 21 17:12:18 2008 @@ -119,7 +119,7 @@ features = '--'.join([normalize(f) for f in features.split('--')]) os.chdir(homedir + '/projects/pypy-dist/pypy/translator/goal') - run('/usr/local/bin/python translate.py --backend=%(backend)s%(featureoptions)s%(translateoptions)s --text --batch targetpypystandalone.py %(targetoptions)s 2>&1' % locals()) + run('/usr/local/bin/python translate.py --backend=%(backend)s%(featureoptions)s%(translateoptions)s --batch targetpypystandalone.py %(targetoptions)s 2>&1' % locals()) if backend == 'llvm': run('mv %s/entry_point.ll %s/pypy.ll' % (tmpdir, tmpdir)) From cfbolz at codespeak.net Wed May 21 17:26:19 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 21 May 2008 17:26:19 +0200 (CEST) Subject: [pypy-svn] r55073 - pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk Message-ID: <20080521152619.B89661684CA@codespeak.net> Author: cfbolz Date: Wed May 21 17:26:18 2008 New Revision: 55073 Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py Log: fix annotation bug Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py Wed May 21 17:26:18 2008 @@ -317,7 +317,7 @@ from pypy.lang.smalltalk import objtable self._w_sender = objtable.w_nil self._stack = [] - self.currentBytecode = None + self.currentBytecode = -1 AbstractRedirectingShadow.__init__(self, w_self) @staticmethod From arigo at codespeak.net Wed May 21 17:34:44 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 21 May 2008 17:34:44 +0200 (CEST) Subject: [pypy-svn] r55074 - in pypy/branch/hybrid-io/pypy: rlib rlib/test rpython rpython/lltypesystem rpython/ootypesystem rpython/test Message-ID: <20080521153444.10E391684D6@codespeak.net> Author: arigo Date: Wed May 21 17:34:43 2008 New Revision: 55074 Modified: pypy/branch/hybrid-io/pypy/rlib/objectmodel.py pypy/branch/hybrid-io/pypy/rlib/test/test_objectmodel.py pypy/branch/hybrid-io/pypy/rpython/lltypesystem/rlist.py pypy/branch/hybrid-io/pypy/rpython/ootypesystem/rlist.py pypy/branch/hybrid-io/pypy/rpython/rlist.py pypy/branch/hybrid-io/pypy/rpython/test/test_rlist.py Log: (fijal, arigo) Kill the objectmodel.newlist(sizehint=...) operation. It was not used at all, so it's decluttering. Modified: pypy/branch/hybrid-io/pypy/rlib/objectmodel.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rlib/objectmodel.py (original) +++ pypy/branch/hybrid-io/pypy/rlib/objectmodel.py Wed May 21 17:34:43 2008 @@ -349,25 +349,3 @@ self.dic = dic self.key = key self.hash = hash - -# ------------------------- optimization hints ------------------------------ - -def newlist(sizehint=0): - return [] - -class Entry(ExtRegistryEntry): - _about_ = newlist - - def compute_result_annotation(self, s_sizehint): - return self.bookkeeper.newlist() - - def specialize_call(self, orig_hop, i_sizehint=None): - from pypy.rpython.rlist import rtype_newlist - from pypy.rpython.lltypesystem import lltype - # fish a bit hop - hop = orig_hop.copy() - v = hop.args_v[0] - r, s = hop.r_s_popfirstarg() - if s.is_constant(): - v = hop.inputconst(r, s.const) - return rtype_newlist(hop, v_sizehint=v) Modified: pypy/branch/hybrid-io/pypy/rlib/test/test_objectmodel.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rlib/test/test_objectmodel.py (original) +++ pypy/branch/hybrid-io/pypy/rlib/test/test_objectmodel.py Wed May 21 17:34:43 2008 @@ -317,32 +317,3 @@ if option.view: graph.show() return graph - -def test_newlist(): - from pypy.annotation.model import SomeInteger - def f(z): - x = newlist(sizehint=38) - if z < 0: - x.append(1) - return len(x) - - graph = getgraph(f, [SomeInteger()]) - for llop in graph.startblock.operations: - if llop.opname == 'malloc_varsize': - break - assert llop.args[2].value == 38 - -def test_newlist_nonconst(): - from pypy.annotation.model import SomeInteger - from pypy.objspace.flow.model import Variable - def f(z): - x = newlist(sizehint=z) - return len(x) - - graph = getgraph(f, [SomeInteger()]) - for llop in graph.startblock.operations: - if llop.opname == 'malloc_varsize': - break - assert llop.args[2] is graph.startblock.inputargs[0] - - Modified: pypy/branch/hybrid-io/pypy/rpython/lltypesystem/rlist.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/lltypesystem/rlist.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/lltypesystem/rlist.py Wed May 21 17:34:43 2008 @@ -71,7 +71,6 @@ ITEMARRAY = GcArray(ITEM, adtmeths = ADTIFixedList({ "ll_newlist": ll_fixed_newlist, - "ll_newlist_hint": ll_fixed_newlist, "ll_newemptylist": ll_fixed_newemptylist, "ll_length": ll_fixed_length, "ll_items": ll_fixed_items, @@ -105,7 +104,6 @@ ("items", Ptr(ITEMARRAY)), adtmeths = ADTIList({ "ll_newlist": ll_newlist, - "ll_newlist_hint": ll_newlist_hint, "ll_newemptylist": ll_newemptylist, "ll_length": ll_length, "ll_items": ll_items, @@ -290,15 +288,6 @@ ll_newlist = typeMethod(ll_newlist) ll_newlist.oopspec = 'newlist(length)' -def ll_newlist_hint(LIST, lengthhint): - ll_assert(lengthhint >= 0, "negative list length") - l = malloc(LIST) - l.length = 0 - l.items = malloc(LIST.items.TO, lengthhint) - return l -ll_newlist_hint = typeMethod(ll_newlist_hint) -ll_newlist_hint.oopspec = 'newlist(length)' - # should empty lists start with no allocated memory, or with a preallocated # minimal number of entries? XXX compare memory usage versus speed, and # check how many always-empty lists there are in a typical pypy-c run... @@ -360,13 +349,10 @@ ll_assert(index < len(l), "fixed setitem out of bounds") l[index] = item -def newlist(llops, r_list, items_v, v_sizehint=None): +def newlist(llops, r_list, items_v): LIST = r_list.LIST if len(items_v) == 0: - if v_sizehint is None: - v_result = llops.gendirectcall(LIST.ll_newemptylist) - else: - v_result = llops.gendirectcall(LIST.ll_newlist_hint, v_sizehint) + v_result = llops.gendirectcall(LIST.ll_newemptylist) else: cno = inputconst(Signed, len(items_v)) v_result = llops.gendirectcall(LIST.ll_newlist, cno) Modified: pypy/branch/hybrid-io/pypy/rpython/ootypesystem/rlist.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/ootypesystem/rlist.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/ootypesystem/rlist.py Wed May 21 17:34:43 2008 @@ -71,7 +71,7 @@ def _make_empty_type(self): return ootype.List() - def _generate_newlist(self, llops, items_v, v_sizehint): + def _generate_newlist(self, llops, items_v): c_list = inputconst(ootype.Void, self.lowleveltype) v_result = llops.genop("new", [c_list], resulttype=self.lowleveltype) c_resize = inputconst(ootype.Void, "_ll_resize") @@ -88,9 +88,8 @@ -def newlist(llops, r_list, items_v, v_sizehint=None): - # XXX do something about v_sizehint - v_result = r_list._generate_newlist(llops, items_v, v_sizehint) +def newlist(llops, r_list, items_v): + v_result = r_list._generate_newlist(llops, items_v) c_setitem = inputconst(ootype.Void, "ll_setitem_fast") for i, v_item in enumerate(items_v): @@ -120,7 +119,7 @@ def make_iterator_repr(self): return ListIteratorRepr(self) - def _generate_newlist(self, llops, items_v, v_sizehint): + def _generate_newlist(self, llops, items_v): c_array = inputconst(ootype.Void, self.lowleveltype) c_length = inputconst(ootype.Signed, len(items_v)) v_result = llops.genop("oonewarray", [c_array, c_length], resulttype=self.lowleveltype) Modified: pypy/branch/hybrid-io/pypy/rpython/rlist.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/rlist.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/rlist.py Wed May 21 17:34:43 2008 @@ -312,7 +312,7 @@ return hop.genop('bool_not', [flag], resulttype=Bool) -def rtype_newlist(hop, v_sizehint=None): +def rtype_newlist(hop): nb_args = hop.nb_args r_list = hop.r_result if r_list == robject.pyobj_repr: # special case: SomeObject lists! @@ -326,8 +326,7 @@ return v_result r_listitem = r_list.item_repr items_v = [hop.inputarg(r_listitem, arg=i) for i in range(nb_args)] - return hop.rtyper.type_system.rlist.newlist(hop.llops, r_list, items_v, - v_sizehint=v_sizehint) + return hop.rtyper.type_system.rlist.newlist(hop.llops, r_list, items_v) def rtype_alloc_and_set(hop): r_list = hop.r_result Modified: pypy/branch/hybrid-io/pypy/rpython/test/test_rlist.py ============================================================================== --- pypy/branch/hybrid-io/pypy/rpython/test/test_rlist.py (original) +++ pypy/branch/hybrid-io/pypy/rpython/test/test_rlist.py Wed May 21 17:34:43 2008 @@ -1354,18 +1354,5 @@ lis = self.interpret(fnpop, [i]) assert list_is_clear(lis, 3-i) - def test_hints(self): - from pypy.rlib.objectmodel import newlist - from pypy.rpython.annlowlevel import hlstr - - def f(z): - z = hlstr(z) - x = newlist(sizehint=13) - x += z - return ''.join(x) - - res = self.interpret(f, [self.string_to_ll('abc')]) - assert self.ll_to_string(res) == 'abc' - class TestOOtype(BaseTestRlist, OORtypeMixin): rlist = oo_rlist From antocuni at codespeak.net Wed May 21 17:50:08 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 21 May 2008 17:50:08 +0200 (CEST) Subject: [pypy-svn] r55075 - in pypy/dist/pypy/lib: . test2 Message-ID: <20080521155008.4473B1684E7@codespeak.net> Author: antocuni Date: Wed May 21 17:50:07 2008 New Revision: 55075 Added: pypy/dist/pypy/lib/test2/test_itertools.py (contents, props changed) Modified: pypy/dist/pypy/lib/itertools.py Log: the logic behind chain.next() was completely broken; add a failing test, and fix it. Modified: pypy/dist/pypy/lib/itertools.py ============================================================================== --- pypy/dist/pypy/lib/itertools.py (original) +++ pypy/dist/pypy/lib/itertools.py Wed May 21 17:50:07 2008 @@ -47,24 +47,15 @@ return self def next(self): - try: - next_elt = self._cur_iterable_iter.next() - except StopIteration: - # The current list's iterator is exhausted, switch to next one - self._cur_iterable_iter = iter(self._iterables_iter.next()) + while True: try: - next_elt = self._cur_iterable_iter.next() + return self._cur_iterable_iter.next() + except StopIteration: + self._cur_iterable_iter = self._iterables_iter.next() except AttributeError: # CPython raises a TypeError when next() is not defined raise TypeError('%s has no next() method' % \ (self._cur_iterable_iter)) - except AttributeError: - # CPython raises a TypeError when next() is not defined - raise TypeError('%s has no next() method' % \ - (self._cur_iterable_iter)) - - return next_elt - class count: """Make an iterator that returns consecutive integers starting Added: pypy/dist/pypy/lib/test2/test_itertools.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/lib/test2/test_itertools.py Wed May 21 17:50:07 2008 @@ -0,0 +1,11 @@ +from pypy.conftest import gettestobjspace + +class AppTestItertools: + def setup_class(cls): + cls.space = gettestobjspace() + cls.w_itertools = cls.space.appexec([], "(): import itertools; return itertools") + + def test_chain(): + it = itertools.chain([], [1, 2, 3]) + lst = list(it) + assert lst == [1, 2, 3] From tverwaes at codespeak.net Wed May 21 18:05:52 2008 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Wed, 21 May 2008 18:05:52 +0200 (CEST) Subject: [pypy-svn] r55077 - pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk Message-ID: <20080521160552.7CC761684F3@codespeak.net> Author: tverwaes Date: Wed May 21 18:05:49 2008 New Revision: 55077 Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/primitives.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/squeakimage.py Log: adding fixes for translation warnings Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py Wed May 21 18:05:49 2008 @@ -181,6 +181,9 @@ hash = UNASSIGNED_HASH # default value + def setchar(self, n0, character): + raise NotImplementedError() + def gethash(self): if self.hash == self.UNASSIGNED_HASH: self.hash = hash = intmask(self.hash_generator.genrand32()) // 2 Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/primitives.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/primitives.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/primitives.py Wed May 21 18:05:49 2008 @@ -326,6 +326,9 @@ def func(interp, w_obj, n0, w_val): val = utility.unwrap_char(w_val) n0 = assert_valid_index(n0, w_obj) + if not (isinstance(w_obj, model.W_CompiledMethod) or + isinstance(w_obj, model.W_BytesObject)): + raise PrimitiveFailedError() w_obj.setchar(n0, val) return w_val Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py Wed May 21 18:05:49 2008 @@ -75,11 +75,13 @@ """A shadow for Smalltalk objects that are classes (i.e. used as the class of another Smalltalk object). """ + def __init__(self, w_self): + self.name = "" + AbstractCachingShadow.__init__(self, w_self) def invalidate_shadow(self): AbstractCachingShadow.invalidate_shadow(self) self.w_methoddict = None self.w_superclass = None - self.name = "" def getname(self): return "%s class" % (self.name or '?',) Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/squeakimage.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/squeakimage.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/squeakimage.py Wed May 21 18:05:49 2008 @@ -324,19 +324,25 @@ def fillin_pointersobject(self, w_pointersobject): assert self.pointers is not None + if w_pointersobject._shadow is not None: + w_pointersobject._shadow.detach_shadow() w_pointersobject._vars = [g_object.w_object for g_object in self.pointers] - w_pointersobject.w_class = self.g_class.w_object + w_class = self.g_class.w_object + assert isinstance(w_class, model.W_PointersObject) + w_pointersobject.w_class = w_class w_pointersobject.hash = self.chunk.hash12 - if w_pointersobject._shadow is not None: - w_pointersobject._shadow.invalidate_shadow() def fillin_wordsobject(self, w_wordsobject): w_wordsobject.words = self.chunk.data - w_wordsobject.w_class = self.g_class.w_object + w_class = self.g_class.w_object + assert isinstance(w_class, model.W_PointersObject) + w_wordsobject.w_class = w_class w_wordsobject.hash = self.chunk.hash12 # XXX check this def fillin_bytesobject(self, w_bytesobject): - w_bytesobject.w_class = self.g_class.w_object + w_class = self.g_class.w_object + assert isinstance(w_class, model.W_PointersObject) + w_bytesobject.w_class = w_class w_bytesobject.bytes = self.get_bytes() w_bytesobject.hash = self.chunk.hash12 # XXX check this def get_bytes(self): From cami at codespeak.net Wed May 21 18:17:26 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Wed, 21 May 2008 18:17:26 +0200 (CEST) Subject: [pypy-svn] r55078 - in pypy/dist/pypy/lang/gameboy: . test Message-ID: <20080521161726.5B84A1684E5@codespeak.net> Author: cami Date: Wed May 21 18:17:24 2008 New Revision: 55078 Modified: pypy/dist/pypy/lang/gameboy/cartridge.py pypy/dist/pypy/lang/gameboy/constants.py pypy/dist/pypy/lang/gameboy/cpu.py pypy/dist/pypy/lang/gameboy/gameboy.py pypy/dist/pypy/lang/gameboy/gameboyImplementation.py pypy/dist/pypy/lang/gameboy/test/test_memory_bank_controller.py pypy/dist/pypy/lang/gameboy/test/test_timer.py pypy/dist/pypy/lang/gameboy/timer.py pypy/dist/pypy/lang/gameboy/video.py Log: fixed bug in timer, which allowed a 0 counter which caused an endless loop int the mainloop. added a lot debug prints, to trace the code Modified: pypy/dist/pypy/lang/gameboy/cartridge.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/cartridge.py (original) +++ pypy/dist/pypy/lang/gameboy/cartridge.py Wed May 21 18:17:24 2008 @@ -264,7 +264,9 @@ def set_rom(self, buffer): banks = int(len(buffer) / constants.ROM_BANK_SIZE) if banks < self.min_rom_bank_size or banks > self.max_rom_bank_size: - raise Exception("Invalid ROM size %s" % hex(len(buffer))) + raise Exception("Invalid ROM size %s, should be in [%s %s]" % \ + (hex(len(buffer)), hex(self.min_rom_bank_size), \ + hex(self.max_rom_bank_size))) self.rom = buffer self.rom_size = constants.ROM_BANK_SIZE * banks - 1 @@ -272,7 +274,9 @@ def set_ram(self, buffer): banks = int(len(buffer) / constants.RAM_BANK_SIZE) if banks < self.min_ram_bank_size or banks > self.max_ram_bank_size: - raise Exception("Invalid RAM size %s" % hex(len(buffer))) + raise Exception("Invalid RAM size %s, should be in [%s %s]" % \ + (hex(len(buffer)), hex(self.min_ram_bank_size), \ + hex(self.max_ram_bank_size))) self.ram = buffer self.ram_size = constants.RAM_BANK_SIZE * banks - 1 Modified: pypy/dist/pypy/lang/gameboy/constants.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/constants.py (original) +++ pypy/dist/pypy/lang/gameboy/constants.py Wed May 21 18:17:24 2008 @@ -7,7 +7,7 @@ REGISTERED_BITMAP = [ 0x3C, 0x42, 0xB9, 0xA5, 0xB9, 0xA5, 0x42, 0x3C ] -GAMEBOY_SCREEN_WIDTH = 160 +GAMEBOY_SCREEN_WIDTH = 160 GAMEBOY_SCREEN_HEIGHT = 144 #___________________________________________________________________________ # CATRIGE TYPES @@ -16,40 +16,40 @@ TYPE_ROM_ONLY = 0x00 -TYPE_MBC1 = 0x01 -TYPE_MBC1_RAM = 0x02 +TYPE_MBC1 = 0x01 +TYPE_MBC1_RAM = 0x02 TYPE_MBC1_RAM_BATTERY = 0x03 -TYPE_MBC2 = 0x05 +TYPE_MBC2 = 0x05 TYPE_MBC2_BATTERY = 0x06 -TYPE_MBC3_RTC_BATTERY = 0x0F +TYPE_MBC3_RTC_BATTERY = 0x0F TYPE_MBC3_RTC_RAM_BATTERY = 0x10 -TYPE_MBC3 = 0x11 -TYPE_MBC3_RAM = 0x12 -TYPE_MBC3_RAM_BATTERY = 0x13 +TYPE_MBC3 = 0x11 +TYPE_MBC3_RAM = 0x12 +TYPE_MBC3_RAM_BATTERY = 0x13 -TYPE_MBC5 = 0x19 -TYPE_MBC5_RAM = 0x1A +TYPE_MBC5 = 0x19 +TYPE_MBC5_RAM = 0x1A TYPE_MBC5_RAM_BATTERY = 0x1B -TYPE_MBC5_RUMBLE = 0x1C -TYPE_MBC5_RUMBLE_RAM = 0x1D +TYPE_MBC5_RUMBLE = 0x1C +TYPE_MBC5_RUMBLE_RAM = 0x1D TYPE_MBC5_RUMBLE_RAM_BATTERY = 0x1E -TYPE_HUC3_RTC_RAM = 0xFE +TYPE_HUC3_RTC_RAM = 0xFE TYPE_HUC1_RAM_BATTERY = 0xFF -CARTRIDGE_TYPE_ADDRESS = 0x0147 +CARTRIDGE_TYPE_ADDRESS = 0x0147 CARTRIDGE_ROM_SIZE_ADDRESS = 0x0148 CARTRIDGE_RAM_SIZE_ADDRESS = 0x0149 CARTRIDGE_RAM_SIZE_MAPPING = {0x00:0, 0x01:8192, 0x02:8192, 0x03:32768} -DESTINATION_CODE_ADDRESS = 0x014A -LICENSEE_ADDRESS = 0x014B -ROM_VERSION_ADDRESS = 0x014C -HEADER_CHECKSUM_ADDRESS = 0x014D -CHECKSUM_A_ADDRESS = 0x014E -CHECKSUM_B_ADDRESS = 0x014F +DESTINATION_CODE_ADDRESS = 0x014A +LICENSEE_ADDRESS = 0x014B +ROM_VERSION_ADDRESS = 0x014C +HEADER_CHECKSUM_ADDRESS = 0x014D +CHECKSUM_A_ADDRESS = 0x014E +CHECKSUM_B_ADDRESS = 0x014F #ROM Bank Size (16KB) ROM_BANK_SIZE = 0x4000 @@ -57,11 +57,9 @@ # constants.RAM Bank Size (8KB) RAM_BANK_SIZE = 0x2000 - - -CARTRIDGE_FILE_EXTENSION = ".gb" +CARTRIDGE_FILE_EXTENSION = ".gb" CARTRIDGE_COLOR_FILE_EXTENSION = ".gbc" -BATTERY_FILE_EXTENSION = ".sav" +BATTERY_FILE_EXTENSION = ".sav" # ___________________________________________________________________________ # CPU FLAGS @@ -72,8 +70,8 @@ H_FLAG = 0x20 C_FLAG = 0x10 -RESET_A = 0x01 -RESET_F = 0x80 +RESET_A = 0x01 +RESET_F = 0x80 RESET_BC = 0x0013 RESET_DE = 0x00D8 RESET_HL = 0x014D @@ -91,8 +89,8 @@ # Interrupt Flags VBLANK = 0x01 # V-Blank Interrupt (INT 40h) -LCD = 0x02 # LCD STAT Interrupt (INT 48h) -TIMER = 0x04 # Timer Interrupt (INT 50h) +LCD = 0x02 # LCD STAT Interrupt (INT 48h) +TIMER = 0x04 # Timer Interrupt (INT 50h) SERIAL = 0x08 # Serial Interrupt (INT 58h) JOYPAD = 0x10 # Joypad Interrupt (INT 60h) @@ -104,16 +102,16 @@ # LCD Register Addresses LCDC = 0xFF40 # LCD Control */ STAT = 0xFF41 # LCD Status */ -SCY = 0xFF42 # BG Scroll Y (0-255) */ -SCX = 0xFF43 # BG Scroll X (0-255) */ -LY = 0xFF44 # LCDC Y-Coordinate (0-153) */ -LYC = 0xFF45 # LY Compare */ -DMA = 0xFF46 # OAM DMA Transfer */ -BGP = 0xFF47 # BG Palette Data */ +SCY = 0xFF42 # BG Scroll Y (0-255) */ +SCX = 0xFF43 # BG Scroll X (0-255) */ +LY = 0xFF44 # LCDC Y-Coordinate (0-153) */ +LYC = 0xFF45 # LY Compare */ +DMA = 0xFF46 # OAM DMA Transfer */ +BGP = 0xFF47 # BG Palette Data */ OBP0 = 0xFF48 # Object Palette 0 Data */ OBP1 = 0xFF49 # Object Palette 1 Data */ -WY = 0xFF4A # Window Y Position (0-143) */ -WX = 0xFF4B # Window X Position (0-166) */ +WY = 0xFF4A # Window Y Position (0-143) */ +WX = 0xFF4B # Window X Position (0-166) */ # OAM Register Addresses OAM_ADDR = 0xFE00 # OAM Object Attribute Map (FE00..FE9F) */ @@ -132,14 +130,14 @@ #LCD Mode Durations -MODE_0_TICKS = 50 # H-Blank */ -MODE_1_TICKS = 114 # V-Blank */ -MODE_2_TICKS = 20 # OAM#/ +MODE_0_TICKS = 50 # H-Blank */ +MODE_1_TICKS = 114 # V-Blank */ +MODE_2_TICKS = 20 # OAM#/ MODE_3_BEGIN_TICKS = 12 # Display */ -MODE_3_END_TICKS = 32 # Display */ +MODE_3_END_TICKS = 32 # Display */ MODE_1_BEGIN_TICKS = 8 # V-Blank Line 144 */ -MODE_1_END_TICKS = 1 # V-Blank Line 153 */ +MODE_1_END_TICKS = 1 # V-Blank Line 153 */ # Objects per Line OBJECTS_PER_LINE = 10 @@ -165,15 +163,15 @@ JOYPAD_CLOCK = GAMEBOY_CLOCK >> 6 -BUTTON_DOWN = 0x08 -BUTTON_UP = 0x04 -BUTTON_LEFT = 0x02 -BUTTON_RIGHT = 0x01 +BUTTON_DOWN = 0x08 +BUTTON_UP = 0x04 +BUTTON_LEFT = 0x02 +BUTTON_RIGHT = 0x01 -BUTTON_START = 0x08 +BUTTON_START = 0x08 BUTTON_SELECT = 0x04 -BUTTON_B = 0x02 -BUTTON_A = 0x01 +BUTTON_B = 0x02 +BUTTON_A = 0x01 @@ -250,7 +248,7 @@ ] # Timer Register Addresses -DIV = 0xFF04 # Divider Register +DIV = 0xFF04 # Divider Register TIMA = 0xFF05 # Timer Counter -TMA = 0xFF06 # Timer Modulo -TAC = 0xFF07 # Timer Control +TMA = 0xFF06 # Timer Modulo +TAC = 0xFF07 # Timer Control Modified: pypy/dist/pypy/lang/gameboy/cpu.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/cpu.py (original) +++ pypy/dist/pypy/lang/gameboy/cpu.py Wed May 21 18:17:24 2008 @@ -166,7 +166,9 @@ self.reset() if isinstance(a, (Register)): a = a.get() + print " "*8, a, "z_flag_compare", self.z_flag self.z_flag = ((a & 0xFF) == 0) + print self.z_flag def c_flag_add(self, s, compare_and=0x01, reset=False): if reset: @@ -184,6 +186,9 @@ # # ------------------------------------------------------------------------------ + +DEBUG_INSTRUCTION_COUNTER = 1 + class CPU(object): """ PyBoy GameBoy (TM) Emulator @@ -230,6 +235,7 @@ self.ime = False self.halted = False self.cycles = 0 + self.instruction_counter = 0 def reset_registers(self): self.a.reset() @@ -239,7 +245,9 @@ self.hl.reset() self.sp.reset() self.pc.reset() - + + # --------------------------------------------------------------- + def get_af(self): return self.af @@ -326,7 +334,9 @@ def set_rom(self, banks): self.rom = banks - + + # --------------------------------------------------------------- + def emulate(self, ticks): ticks = int(ticks) self.cycles += ticks @@ -356,14 +366,33 @@ def fetch_execute(self): # Execution opCode = self.fetch() - print " fetch exe:", hex(opCode) + print " fetch exe:", hex(opCode), " " + #, FETCH_EXECUTE_OP_CODES[opCode].__name__ FETCH_EXECUTE_OP_CODES[opCode](self) + def execute(self, opCode): - print "-"*60 - print "exe: ", hex(opCode), "|", hex(self.pc.get()), hex(self.sp.get()) + self.instruction_counter += 1 + print self.instruction_counter, "-"*60 + print "exe: ", hex(opCode), " " + #, OP_CODES[opCode].__name__ + print " pc:", hex(self.pc.get()), "sp:", hex(self.sp.get()) + self.print_registers() OP_CODES[opCode](self) + def print_registers(self): + print " a: "+hex(self.a.get()) + str = " af: "+hex(self.af.get()) + str += " bc: "+hex(self.bc.get()) + str += " de: "+hex(self.de.get()) + str += " hl: "+hex(self.hl.get()) + print str + + # ------------------------------------------------------------------- + + def debug(self): + print "0xDD called" + def read(self, hi, lo=None): # memory Access, 1 cycle address = hi @@ -979,11 +1008,13 @@ def group_lambda(function, register_getter, value=None): if value is None: - return lambda s: function(s, RegisterCallWrapper(register_getter(s)), \ + def f(s): function(s, RegisterCallWrapper(register_getter(s)), \ RegisterCallWrapper(register_getter(s))) else: - return lambda s: function(s, RegisterCallWrapper(register_getter(s)), \ + def f(s): function(s, RegisterCallWrapper(register_getter(s)), \ RegisterCallWrapper(register_getter(s)), value) + f.__name__ += function.__name__ + return f def create_load_group_op_codes(): opCodes = [] @@ -996,9 +1027,10 @@ return opCodes def load_group_lambda(store_register, load_register): - return lambda s: CPU.ld(s, RegisterCallWrapper(load_register(s)), \ + def f(s): CPU.ld(s, RegisterCallWrapper(load_register(s)), \ RegisterCallWrapper(store_register(s))) - + f.__name__ += "ld" + return f def create_register_op_codes(table): opCodes = [] @@ -1064,6 +1096,7 @@ (0xC3, CPU.unconditional_jump), (0xC9, CPU.ret), (0xD9, CPU.return_form_interrupt), + (0xDD, CPU.debug), (0xE9, CPU.store_hl_in_pc), (0xF9, CPU.store_hl_in_sp), (0xE0, CPU.write_a_at_expanded_fetch_address), Modified: pypy/dist/pypy/lang/gameboy/gameboy.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/gameboy.py (original) +++ pypy/dist/pypy/lang/gameboy/gameboy.py Wed May 21 18:17:24 2008 @@ -24,7 +24,7 @@ self.create_gamboy_elements() def create_drivers(self): - self.clock = Clock() + self.clock = Clock() self.joypad_driver = JoypadDriver() self.video_driver = VideoDriver() self.sound_driver = SoundDriver() @@ -87,16 +87,27 @@ def emulate(self, ticks): while ticks > 0: count = self.get_cycles() + #print "emulating", ticks, "cycles, available", count self.cpu.emulate(count) self.serial.emulate(count) self.timer.emulate(count) self.video.emulate(count) self.sound.emulate(count) self.joypad.emulate(count) + #self.print_cycles() if count == 0: - break + self.print_cycles() + return 0 ticks -= count return 0 + + def print_cycles(self): + for element in [(" video:", self.video), + ("serial:", self.serial), + (" timer:", self.timer), + (" sound:", self.sound), + ("joypad:", self.joypad)]: + print " ", element[0], element[1].get_cycles() def write(self, address, data): receiver = self.get_receiver(address) @@ -111,7 +122,7 @@ return receiver.read(address) def print_receiver_msg(self, address, name): - print " mem.receiver ", hex(address), name + print " recei: ", hex(address), name def get_receiver(self, address): if 0x0000 <= address <= 0x7FFF: Modified: pypy/dist/pypy/lang/gameboy/gameboyImplementation.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/gameboyImplementation.py (original) +++ pypy/dist/pypy/lang/gameboy/gameboyImplementation.py Wed May 21 18:17:24 2008 @@ -5,6 +5,8 @@ from pypy.lang.gameboy.video import VideoDriver from pypy.lang.gameboy.sound import SoundDriver from pypy.lang.gameboy.timer import Clock +from pypy.lang.gameboy import constants + from pypy.rlib.rsdl import RSDL, RSDL_helper from pypy.rpython.lltypesystem import lltype, rffi from pypy.rlib.objectmodel import specialize @@ -36,8 +38,8 @@ if self.check_for_escape(): break self.joypad_driver.update(self.event) - self.emulate(10) - RSDL.Delay(10) + self.emulate(constants.GAMEBOY_CLOCK >> 2) + RSDL.Delay(100) finally: lltype.free(self.event, flavor='raw') RSDL.Quit() @@ -77,10 +79,24 @@ pass def draw_pixels(self): + print "-"*60 for x in range(self.width): + str = "" for y in range(self.height): - RSDL_helper.set_pixel(self.screen, x, y, self.get_pixel_color(x, y)) - + str += self.pixel_map(x, y) + #RSDL_helper.set_pixel(self.screen, x, y, self.get_pixel_color(x, y)) + print str; + + print "-"*60 + + def pixel_map(self, x, y): + px = self.get_pixel_color(x, y) + b = px & 0xFF + g = (px>>8) & 0xFF + r = (px>>16) & 0xFF + brightness = 4*r+b+g / 0xFFFFFF + return [".", "+", "O", "#"][brightness] + def get_pixel_color(self, x, y): return self.pixels[x+self.width*y] #return self.map[self.pixels[x+self.width*y]] @@ -102,7 +118,6 @@ def update(self, event): # fetch the event from sdl type = rffi.getintfield(event, 'c_type') - print "JoypadDriver.update ", type if type == RSDL.KEYDOWN: self.create_called_key(event) self.on_key_down() Modified: pypy/dist/pypy/lang/gameboy/test/test_memory_bank_controller.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/test/test_memory_bank_controller.py (original) +++ pypy/dist/pypy/lang/gameboy/test/test_memory_bank_controller.py Wed May 21 18:17:24 2008 @@ -89,17 +89,101 @@ pass mbc.ram_enable = True assert mbc.read(0xA000) == value + +# ----------------------------------------------------------------------------- + +def get_default_mbc(): + return DefaultMBC([0]*0xFFFF, [0]*0xFFFF, get_clock_driver()) + +def test_default_mbc_read(): + py.test.skip("not yet implemented") + mbc = get_default_mbc() + +def test_default_mbc_write(): + py.test.skip("not yet implemented") + mbc = get_default_mbc() - +# ----------------------------------------------------------------------------- + +def get_mbc1(): + return MBC1([0]*0x5FFF,[0]*0xBFFF, get_clock_driver()) def test_mbc1_write(): py.test.skip("buggy implementation of MBC1++") - mbc1 = MBC1([0]*0x5FFF,[0]*0xBFFF, get_clock_driver()) + mbc1 = get_mbc1() test_mbc_read_write_test(mbc1) + +def test_mbc1_read(): + py.test.skip("not yet implemented") + mbc1 = get_mbc1() + # the same as in mbc + pass + +# ----------------------------------------------------------------------------- + +def get_mbc2(): + return MBC2([0]*0x5FFF,[0]*0xBFFF, get_clock_driver()) +def test_mbc2_read_write(): + py.test.skip("not yet implemented") + mbc2 = get_mbc2() + +def test_mbc2_write(): + py.test.skip("not yet implemented") + mbc2 = get_mbc2() + +# ----------------------------------------------------------------------------- + +def get_mbc3(): + return MBC3([0]*0x5FFF,[0]*0xBFFF, get_clock_driver()) + +def test_mbc3_read(): + py.test.skip("not yet implemented") + mbc3 = get_mbc3() + +def test_mbc3_write(): + py.test.skip("not yet implemented") + mbc3 = get_mbc3() +# ----------------------------------------------------------------------------- +def get_mbc5(): + return MBC5([0]*0x5FFF,[0]*0xBFFF, get_clock_driver()) +def test_mbc5_read(): + py.test.skip("not yet implemented") + mbc5 = get_mbc5() + +def test_mbc5_write(): + py.test.skip("not yet implemented") + mbc5 = get_mbc5() + +# ----------------------------------------------------------------------------- + +def get_huc1(): + return HuC1([0]*0x5FFF,[0]*0xBFFF, get_clock_driver()) - \ No newline at end of file +def test_huc1_read(): + py.test.skip("not yet implemented") + huc1 = get_huc1() + +def test_huc1_write(): + py.test.skip("not yet implemented") + huc1 = get_huc1() + +# ----------------------------------------------------------------------------- + +def get_huc3(): + return HuC3([0]*0x5FFF,[0]*0xBFFF, get_clock_driver()) + +def test_huc3_read(): + py.test.skip("not yet implemented") + huc3 = get_huc3() + +def test_huc3_write(): + py.test.skip("not yet implemented") + huc3 = get_huc3() + +# ----------------------------------------------------------------------------- + Modified: pypy/dist/pypy/lang/gameboy/test/test_timer.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/test/test_timer.py (original) +++ pypy/dist/pypy/lang/gameboy/test/test_timer.py Wed May 21 18:17:24 2008 @@ -66,7 +66,7 @@ assert timer.timer_clock == 0 assert timer.timer_clock == 0 -def test_read_write_Divider(): +def test_read_write_divider(): timer = get_timer() value = 0x12 timer.div = value @@ -85,13 +85,13 @@ timer.timer_cycles = value assert timer.get_cycles() == timer.timer_cycles -def test_emulateDivider_normal(): +def test_emulate_divider_normal(): timer = get_timer() value = 2 timer.timer_cycles = 0 timer.emulate_timer(value) -def test_test_emulateDivider_zero(): +def test_test_emulate_divider_zero(): timer = get_timer() value = 2 timer.timer_cycles = value Modified: pypy/dist/pypy/lang/gameboy/timer.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/timer.py (original) +++ pypy/dist/pypy/lang/gameboy/timer.py Wed May 21 18:17:24 2008 @@ -23,9 +23,10 @@ self.divider_cycles = constants.DIV_CLOCK self.tima = 0 self.tma = 0 - self.tac = 0x00 + self.tac = 0 self.timer_cycles = constants.TIMER_CLOCK[0] self.timer_clock = constants.TIMER_CLOCK[0] + print constants.TIMER_CLOCK def write(self, address, data): address = int(address) @@ -73,7 +74,8 @@ def set_timer_control(self, data): if (self.tac & 0x03) != (data & 0x03): - self.timer_clock = self.timer_cycles = constants.TIMER_CLOCK[data & 0x03] + self.timer_clock = constants.TIMER_CLOCK[data & 0x03] + self.timer_cycles = constants.TIMER_CLOCK[data & 0x03] self.tac = data def get_cycles(self): @@ -82,37 +84,29 @@ return self.divider_cycles def emulate(self, ticks): - ticks = int(ticks) self.emulate_divider(ticks) self.emulate_timer(ticks) def emulate_divider(self, ticks): - ticks = int(ticks) self.divider_cycles -= ticks if self.divider_cycles > 0: return - count = int(ceil(-1.0*self.divider_cycles / constants.DIV_CLOCK)) - self.div = (self.div + count) & 0xFF - self.divider_cycles += constants.DIV_CLOCK*count + while self.divider_cycles <= 0: + self.div = (self.div + 1) & 0xFF; + self.divider_cycles += constants.DIV_CLOCK; + print self.divider_cycles def emulate_timer(self, ticks): - ticks = int(ticks) if (self.tac & 0x04) == 0: return self.timer_cycles -= ticks - if self.timer_cycles > 0: - return - count = int(ceil(-1.0*self.timer_cycles / self.timer_clock)) - self.tima_zero_pass_check(count) - self.tima = (self.tima + count) & 0xFF - self.timer_cycles += self.timer_clock * count - - def tima_zero_pass_check(self, count): - if (self.tima < 0) and (self.tima + count >= 0): - self.tima = self.tma - count - self.interrupt.raise_interrupt(constants.TIMER) - #print self.interrupt.timer.is_pending(), self.interrupt.is_pending(constants.TIMER) - + while self.timer_cycles <= 0: + self.tima = (self.tima + 1) & 0xFF + self.timer_cycles += self.timer_clock + if self.tima == 0x00: + self.tima = self.tma + self.interrupt.raise_interrupt(constants.TIMER) + # CLOCK DRIVER ----------------------------------------------------------------- class Clock(object): Modified: pypy/dist/pypy/lang/gameboy/video.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/video.py (original) +++ pypy/dist/pypy/lang/gameboy/video.py Wed May 21 18:17:24 2008 @@ -193,12 +193,12 @@ def reset_control(self, data): # NOTE: do not reset constants.LY=LYC flag (bit 2) of the STAT register (Mr. Do!) if (data & 0x80) != 0: - self.stat = (self.stat & 0xFC) | 0x02 - self.cycles = constants.MODE_2_TICKS - self.line_y = 0 + self.stat = (self.stat & 0xFC) | 0x02 + self.cycles = constants.MODE_2_TICKS + self.line_y = 0 self.display = False else: - self.stat = (self.stat & 0xFC) | 0x00 + self.stat = (self.stat & 0xFC) | 0x00 self.cycles = constants.MODE_1_TICKS self.line_y = 0 self.clear_frame() From karlb at codespeak.net Wed May 21 19:32:49 2008 From: karlb at codespeak.net (karlb at codespeak.net) Date: Wed, 21 May 2008 19:32:49 +0200 (CEST) Subject: [pypy-svn] r55079 - in pypy/dist/pypy/rlib/rsdl: . test Message-ID: <20080521173249.62B742A8002@codespeak.net> Author: karlb Date: Wed May 21 19:32:44 2008 New Revision: 55079 Modified: pypy/dist/pypy/rlib/rsdl/RMix.py pypy/dist/pypy/rlib/rsdl/RSDL.py pypy/dist/pypy/rlib/rsdl/test/test_sdl_mixer.py Log: Added support for LoadWAV to RMix Modified: pypy/dist/pypy/rlib/rsdl/RMix.py ============================================================================== --- pypy/dist/pypy/rlib/rsdl/RMix.py (original) +++ pypy/dist/pypy/rlib/rsdl/RMix.py Wed May 21 19:32:44 2008 @@ -2,16 +2,47 @@ from pypy.rpython.tool import rffi_platform as platform from pypy.translator.tool.cbuild import ExternalCompilationInfo from pypy.rlib.rsdl import RSDL +import sys -eci = ExternalCompilationInfo( - includes=['SDL_mixer.h'], - libraries=['SDL_mixer'], +if sys.platform == 'darwin': + eci = ExternalCompilationInfo( + includes = ['SDL_mixer.h'], + frameworks = ['SDL_mixer'], + include_dirs = ['/Library/Frameworks/SDL_Mixer.framework/Versions/A/Headers'] ) +else: + eci = ExternalCompilationInfo( + includes=['SDL_mixer.h'], + libraries=['SDL_mixer'], + ) + eci = eci.merge(RSDL.eci) +ChunkPtr = lltype.Ptr(lltype.ForwardReference()) + +class CConfig: + _compilation_info_ = eci + + Chunk = platform.Struct('Mix_Chunk', []) + +globals().update(platform.configure(CConfig)) + +ChunkPtr.TO.become(Chunk) + def external(name, args, result): return rffi.llexternal(name, args, result, compilation_info=eci) OpenAudio = external('Mix_OpenAudio', - [rffi.INT, RSDL.Uint16, rffi.INT, rffi.INT], - rffi.INT) + [rffi.INT, RSDL.Uint16, rffi.INT, rffi.INT], + rffi.INT) + +CloseAudio = external('Mix_CloseAudio', [], lltype.Void) + +_LoadWAV = external('Mix_LoadWAV_RW', + [RSDL.RWopsPtr, rffi.INT], + ChunkPtr) + +def LoadWAV(filename_ccharp): + _LoadWAV(RSDL.RWFromFile(filename_ccharp, rffi.str2charp('rb')), 1) + + Modified: pypy/dist/pypy/rlib/rsdl/RSDL.py ============================================================================== --- pypy/dist/pypy/rlib/rsdl/RSDL.py (original) +++ pypy/dist/pypy/rlib/rsdl/RSDL.py Wed May 21 19:32:44 2008 @@ -44,6 +44,7 @@ MouseButtonEventPtr = lltype.Ptr(lltype.ForwardReference()) MouseMotionEventPtr = lltype.Ptr(lltype.ForwardReference()) KeyPtr = lltype.Ptr(lltype.ForwardReference()) +RWopsPtr = lltype.Ptr(lltype.ForwardReference()) # ------------------------------------------------------------------------------ @@ -105,6 +106,7 @@ ('xrel', rffi.INT), ('yrel', rffi.INT)]) + RWops = platform.Struct('SDL_RWops', []) # ------------------------------------------------------------------------------ @@ -125,6 +127,7 @@ KeyboardEventPtr.TO.become(KeyboardEvent) MouseButtonEventPtr.TO.become(MouseButtonEvent) MouseMotionEventPtr.TO.become(MouseMotionEvent) +RWopsPtr.TO.become(RWops) # ------------------------------------------------------------------------------ @@ -238,6 +241,10 @@ [], rffi.CCHARP) +RWFromFile = external('SDL_RWFromFile', + [rffi.CCHARP, rffi.CCHARP], + RWopsPtr) + # ------------------------------------------------------------------------------ Modified: pypy/dist/pypy/rlib/rsdl/test/test_sdl_mixer.py ============================================================================== --- pypy/dist/pypy/rlib/rsdl/test/test_sdl_mixer.py (original) +++ pypy/dist/pypy/rlib/rsdl/test/test_sdl_mixer.py Wed May 21 19:32:44 2008 @@ -7,3 +7,13 @@ if RMix.OpenAudio(22050, RSDL.AUDIO_S16LSB, 2, 1024) != 0: error = rffi.charp2str(RSDL.GetError()) raise Exception(error) + RMix.CloseAudio() + +def test_load_wav(): + if RMix.OpenAudio(22050, RSDL.AUDIO_S16LSB, 2, 1024) != 0: + error = rffi.charp2str(RSDL.GetError()) + raise Exception(error) + filename = rffi.str2charp('test.wav') + RMix.LoadWAV(filename) + rffi.free_charp(filename) + RMix.CloseAudio() From pypy-svn at codespeak.net Wed May 21 20:30:08 2008 From: pypy-svn at codespeak.net (VIAGRA ® Official Site) Date: Wed, 21 May 2008 20:30:08 +0200 (CEST) Subject: [pypy-svn] Dear pypy-svn@codespeak.net May 82% 0FF Message-ID: <20080521132832.4012.qmail@ppp25-43.pppoe.mtu-net.ru> An HTML attachment was scrubbed... URL: From fijal at codespeak.net Wed May 21 20:48:57 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 21 May 2008 20:48:57 +0200 (CEST) Subject: [pypy-svn] r55080 - pypy/extradoc/talk/ep2008 Message-ID: <20080521184857.B04ED168477@codespeak.net> Author: fijal Date: Wed May 21 20:48:55 2008 New Revision: 55080 Added: pypy/extradoc/talk/ep2008/ Log: Directory for ep2008 abstracts From fijal at codespeak.net Wed May 21 20:55:46 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 21 May 2008 20:55:46 +0200 (CEST) Subject: [pypy-svn] r55081 - pypy/extradoc/talk/ep2008 Message-ID: <20080521185546.D6359168477@codespeak.net> Author: fijal Date: Wed May 21 20:55:41 2008 New Revision: 55081 Added: pypy/extradoc/talk/ep2008/abstract.txt (contents, props changed) Log: Check in a basic format for abstract, just because it's easier to work from this point Added: pypy/extradoc/talk/ep2008/abstract.txt ============================================================================== --- (empty file) +++ pypy/extradoc/talk/ep2008/abstract.txt Wed May 21 20:55:41 2008 @@ -0,0 +1,23 @@ +Title +===== + +(Snappy title, e.g. Fly Fishing and Python 3000). + +Summary +======= + +(One line summary, e.g. How the new version of Python will affect your bait). + +Abstract +======== + +(Please explain what your talk will cover in a couple of paragraphs). + +Proposed Length of talk required +================================ + +(e.g. 30, 45 or 60 minutes). + +Brief Biography +=============== + From fijal at codespeak.net Wed May 21 21:15:53 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 21 May 2008 21:15:53 +0200 (CEST) Subject: [pypy-svn] r55082 - pypy/extradoc/talk/ep2008 Message-ID: <20080521191553.5D5ED1683D0@codespeak.net> Author: fijal Date: Wed May 21 21:15:47 2008 New Revision: 55082 Added: pypy/extradoc/talk/ep2008/abstract_obscure.txt (contents, props changed) pypy/extradoc/talk/ep2008/abstract_status.txt (contents, props changed) Log: Quick abstracts to submit in desired deadline. Added: pypy/extradoc/talk/ep2008/abstract_obscure.txt ============================================================================== --- (empty file) +++ pypy/extradoc/talk/ep2008/abstract_obscure.txt Wed May 21 21:15:47 2008 @@ -0,0 +1,36 @@ +Title +===== + +PyPy - garbage collection details. + +Summary +======= + +Obscure, naked, details of garbage collection strategies available in pypy. +Will contain performance difference of various operations depending on +chosen GC. + +Abstract +======== + +In this talk, we'll cover garbage collection strategies present in PyPy. +We'll not go into implementation details of those, but instead we'll +try to explain how certain operations behave and especially how they +present different performance characteristics than cpython's reference +counting strategy. We'll also explain why certain programming patterns +work well on some garbage collectors and doesn't work too well on others +and how to avoid such obstacles. + +Proposed Length of talk required +================================ + +30 minutes. + +Brief Biography +=============== + +Maciej Fijalkowski is a core pypy developer, particularly interested +in obscure details of various parts. + +Armin Rigo is the author of psyco JIT, as well as key person behind +most pypy's obscure advanced details. Added: pypy/extradoc/talk/ep2008/abstract_status.txt ============================================================================== --- (empty file) +++ pypy/extradoc/talk/ep2008/abstract_status.txt Wed May 21 21:15:47 2008 @@ -0,0 +1,30 @@ +Title +===== + +PyPy status talk. + +Summary +======= + +Quick summary of cool features of pypy, where we are now and where we are going. + +Abstract +======== + +This talk will try to explain to broader public status of the PyPy project, +where we are and where we are going. We're going to show some demos of +cool features, but also we're going to run real applications on top of pypy +to showcase how complaint our python interpreter is. + +This talk will not cover any internal details (or at least not that many :), +which will be covered by different talk. + +Proposed Length of talk required +================================ + +45 minutes. + +Brief Biography +=============== + +Maciej Fijalkowski is a core pypy developer. From cfbolz at codespeak.net Thu May 22 09:20:43 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 22 May 2008 09:20:43 +0200 (CEST) Subject: [pypy-svn] r55120 - pypy/branch/smalltalk-shadow-changes/pypy/translator/backendopt/test Message-ID: <20080522072043.D65F216854B@codespeak.net> Author: cfbolz Date: Thu May 22 09:20:42 2008 New Revision: 55120 Modified: pypy/branch/smalltalk-shadow-changes/pypy/translator/backendopt/test/test_malloc.py Log: failing test about malloc removal in the presence of cast_pointers. The problem is that malloc removal replaces each occurence of the same structure in the input args of a block by the exploded vars, which means that there is no global view of what the variables currently are. Modified: pypy/branch/smalltalk-shadow-changes/pypy/translator/backendopt/test/test_malloc.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/translator/backendopt/test/test_malloc.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/translator/backendopt/test/test_malloc.py Thu May 22 09:20:42 2008 @@ -334,6 +334,18 @@ [link] = entrymap[graph.returnblock] assert link.prevblock.operations[-1].opname == 'keepalive' + def test_nested_struct(self): + py.test.skip("XXX fix me!") + S = lltype.GcStruct("S", ('x', lltype.Signed)) + T = lltype.GcStruct("T", ('s', S)) + def f(x): + t = lltype.malloc(T) + s = t.s + if x: + s.x = x + return t.s.x + s.x + graph = self.check(f, [int], [42], 2 * 42) + def test_interior_ptr(self): py.test.skip("fails") S = lltype.Struct("S", ('x', lltype.Signed)) From tverwaes at codespeak.net Thu May 22 10:08:31 2008 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Thu, 22 May 2008 10:08:31 +0200 (CEST) Subject: [pypy-svn] r55121 - pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk Message-ID: <20080522080831.A16B5168561@codespeak.net> Author: tverwaes Date: Thu May 22 10:08:28 2008 New Revision: 55121 Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py Log: allocate less space for blocks Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py Thu May 22 10:08:28 2008 @@ -513,7 +513,8 @@ # create and attach a shadow manually, to not have to carefully put things # into the right places in the W_PointersObject # XXX could hack some more to never have to create the _vars of w_result - w_result = model.W_PointersObject(w_BlockContext, w_home.size()) + contextsize = w_home.as_methodcontext_get_shadow().myblocksize() + w_result = model.W_PointersObject(w_BlockContext, contextsize) s_result = BlockContextShadow(w_result) w_result.store_shadow(s_result) s_result.store_expected_argument_count(argcnt) @@ -698,3 +699,6 @@ def stackstart(self): return (constants.MTHDCTX_TEMP_FRAME_START + self.w_method().tempframesize()) + + def myblocksize(self): + return self.size() - self.tempframesize() From afa at codespeak.net Thu May 22 13:31:06 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Thu, 22 May 2008 13:31:06 +0200 (CEST) Subject: [pypy-svn] r55127 - in pypy/branch/win32port/pypy/translator/goal: . test2 Message-ID: <20080522113106.A2A56168421@codespeak.net> Author: afa Date: Thu May 22 13:31:05 2008 New Revision: 55127 Modified: pypy/branch/win32port/pypy/translator/goal/nanos.py pypy/branch/win32port/pypy/translator/goal/test2/test_nanos.py Log: Loading nanos has the side-effect of inserting the os module in sys.modules, which causes the whole os.pyc to be embedded as a frozen module inside pypy-c. The effect was that on Windows, the frozen os.pyc contains a reference to a posix.environ which is different from the posix.environ which gets initialized on pypy-c startup. Why only on Windows? Maybe because the posix module is named "nt"; it's possible that the module is initialized twice, and this should be corrected. Anyway, it seems better to not embed os.pyc in pypy-c, and let it load the actual file when it starts. Now os.environ is correctly initialized on Windows. Phew. Modified: pypy/branch/win32port/pypy/translator/goal/nanos.py ============================================================================== --- pypy/branch/win32port/pypy/translator/goal/nanos.py (original) +++ pypy/branch/win32port/pypy/translator/goal/nanos.py Thu May 22 13:31:05 2008 @@ -29,17 +29,25 @@ import os app_os_path = applevel(r''' - # NOT_RPYTHON from os.path import dirname, join, abspath, isfile, islink ''', filename=__file__) app_os = applevel(r''' # NOT_RPYTHON + import sys + sysmodules = sys.modules.keys() + from os import sep, pathsep, getenv, name, fdopen try: from os import readlink except ImportError: pass + + # restore the previous list of loaded modules + for name in sys.modules.keys(): + if name not in sysmodules: + del sys.modules[name] + del sys ''', filename=__file__) def getenv(space, w_name): Modified: pypy/branch/win32port/pypy/translator/goal/test2/test_nanos.py ============================================================================== --- pypy/branch/win32port/pypy/translator/goal/test2/test_nanos.py (original) +++ pypy/branch/win32port/pypy/translator/goal/test2/test_nanos.py Thu May 22 13:31:05 2008 @@ -17,4 +17,10 @@ w_dict = space.newdict() space.exec_(open(filename).read(), w_dict, w_dict) entry_point = create_entry_point(space, w_dict) + + # check that 'os' is not in sys.modules + assert not space.is_true( + space.call_method(space.sys.get('modules'), + '__contains__', space.wrap('os'))) + entry_point(['', '-c', 'print 42']) From tverwaes at codespeak.net Thu May 22 14:14:57 2008 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Thu, 22 May 2008 14:14:57 +0200 (CEST) Subject: [pypy-svn] r55129 - in pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk: . test Message-ID: <20080522121457.97C30168457@codespeak.net> Author: tverwaes Date: Thu May 22 14:14:55 2008 New Revision: 55129 Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_interpreter.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_miniimage.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_shadow.py Log: len(mcs.temps) == w_method.tempsize instead of w_method.tempsize + w_method.argsize. Fixed code + tests + renamed one masked test Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py Thu May 22 14:14:55 2008 @@ -536,13 +536,11 @@ self.header = header self.argsize = numargs self.tempsize = tempsize + assert self.tempsize >= self.argsize self.primitive = primitive self.w_compiledin = None self.islarge = islarge - def tempframesize(self): - return self.argsize + self.tempsize - def literalat0(self, index0): if index0 == 0: from pypy.lang.smalltalk import utility Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py Thu May 22 14:14:55 2008 @@ -365,7 +365,7 @@ # tempframe start # Stackpointer from smalltalk world == stacksize in python world self.store_stackpointer(utility.unwrap_int(w_sp1) - - self.tempframesize()) + self.tempsize()) def store_stackpointer(self, size): from pypy.lang.smalltalk import objtable @@ -379,7 +379,7 @@ def wrap_stackpointer(self): return utility.wrap_int(len(self._stack) + - self.tempframesize()) + self.tempsize()) def external_stackpointer(self): return len(self._stack) + self.stackstart() @@ -502,7 +502,7 @@ # XXX this is incorrect when there is subclassing return self._w_self_size - def tempframesize(self): + def tempsize(self): raise NotImplementedError() class BlockContextShadow(ContextPartShadow): @@ -592,7 +592,7 @@ def stackpointer_offset(self): return constants.BLKCTX_STACK_START - def tempframesize(self): + def tempsize(self): # A blockcontext doesn't have any temps return 0 @@ -623,7 +623,7 @@ s_result.store_w_sender(w_sender) s_result.store_w_receiver(w_receiver) s_result.store_pc(0) - s_result._temps = [objtable.w_nil] * w_method.tempframesize() + s_result._temps = [objtable.w_nil] * w_method.tempsize for i in range(len(arguments)): s_result.settemp(i, arguments[i]) return w_result @@ -636,7 +636,7 @@ if n0 == constants.MTHDCTX_RECEIVER: return self.w_receiver() if (0 <= n0-constants.MTHDCTX_TEMP_FRAME_START < - self.w_method().tempframesize()): + self.tempsize()): return self.gettemp(n0-constants.MTHDCTX_TEMP_FRAME_START) else: return ContextPartShadow.fetch(self, n0) @@ -651,7 +651,7 @@ self.store_w_receiver(w_value) return if (0 <= n0-constants.MTHDCTX_TEMP_FRAME_START < - self.w_method().tempframesize()): + self.tempsize()): return self.settemp(n0-constants.MTHDCTX_TEMP_FRAME_START, w_value) else: @@ -662,11 +662,11 @@ # Make sure the method is updated first self.copy_from_w_self(constants.MTHDCTX_METHOD) # And that there is space for the temps - self._temps = [objtable.w_nil] * self.w_method().tempframesize() + self._temps = [objtable.w_nil] * self.tempsize() ContextPartShadow.attach_shadow(self) - def tempframesize(self): - return self.w_method().tempframesize() + def tempsize(self): + return self.w_method().tempsize def w_method(self): return self._w_method @@ -698,7 +698,7 @@ def stackstart(self): return (constants.MTHDCTX_TEMP_FRAME_START + - self.w_method().tempframesize()) + self.tempsize()) def myblocksize(self): - return self.size() - self.tempframesize() + return self.size() - self.tempsize() Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_interpreter.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_interpreter.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_interpreter.py Thu May 22 14:14:55 2008 @@ -423,6 +423,7 @@ method.literalsize = 1 method.bytes = bytecode method.argsize = 1 + method.tempsize = 1 method.literals = fakeliterals("fib:") shadow.installmethod("fib:", method) w_object = shadow.new() @@ -548,6 +549,7 @@ shadow = mockclass(0).as_class_get_shadow() w_method = model.W_CompiledMethod(0) w_method.argsize = 1 + w_method.tempsize = 1 w_method.literalsize = 1 shadow.installmethod("+", w_method) Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_miniimage.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_miniimage.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_miniimage.py Thu May 22 14:14:55 2008 @@ -283,10 +283,10 @@ from pypy.lang.smalltalk import wrapper ap = wrapper.ProcessWrapper(wrapper.scheduler().active_process()) s_ctx = ap.suspended_context().as_context_get_shadow() - assert isinstance(s_ctx, shadow.BlockContextShadow) + assert isinstance(s_ctx, shadow.MethodContextShadow) assert s_ctx.top().is_same_object(objtable.w_true) -def test_step_forged_image(): +def test_step_run_something(): setup_module(None, filename='running-something-mini.image') from pypy.lang.smalltalk import wrapper ap = wrapper.ProcessWrapper(wrapper.scheduler().active_process()) Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_shadow.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_shadow.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_shadow.py Thu May 22 14:14:55 2008 @@ -79,10 +79,10 @@ def methodcontext(w_sender=objtable.w_nil, pc=1, stackpointer=0, stacksize=5, method=method()): - w_object = model.W_PointersObject(classtable.w_MethodContext, constants.MTHDCTX_TEMP_FRAME_START+method.tempframesize()+stacksize) + w_object = model.W_PointersObject(classtable.w_MethodContext, constants.MTHDCTX_TEMP_FRAME_START+method.tempsize+stacksize) w_object.store(constants.CTXPART_SENDER_INDEX, w_sender) w_object.store(constants.CTXPART_PC_INDEX, utility.wrap_int(pc)) - w_object.store(constants.CTXPART_STACKP_INDEX, utility.wrap_int(method.tempframesize()+stackpointer)) + w_object.store(constants.CTXPART_STACKP_INDEX, utility.wrap_int(method.tempsize+stackpointer)) w_object.store(constants.MTHDCTX_METHOD, method) # XXX w_object.store(constants.MTHDCTX_RECEIVER_MAP, '???') From tverwaes at codespeak.net Thu May 22 14:19:35 2008 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Thu, 22 May 2008 14:19:35 +0200 (CEST) Subject: [pypy-svn] r55130 - pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk Message-ID: <20080522121935.C6177168453@codespeak.net> Author: tverwaes Date: Thu May 22 14:19:34 2008 New Revision: 55130 Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py Log: apparently not all contexts have an initialized pc. Assume that this will be stored later on. Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py Thu May 22 14:19:34 2008 @@ -416,6 +416,9 @@ return w_sender.as_context_get_shadow() def store_unwrap_pc(self, w_pc): + from pypy.lang.smalltalk import objtable + if w_pc.is_same_object(objtable.w_nil): + return pc = utility.unwrap_int(w_pc) pc -= self.w_method().bytecodeoffset() pc -= 1 From afa at codespeak.net Thu May 22 17:33:59 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Thu, 22 May 2008 17:33:59 +0200 (CEST) Subject: [pypy-svn] r55132 - pypy/branch/win32port/pypy/rpython/tool/test Message-ID: <20080522153359.9B712168444@codespeak.net> Author: afa Date: Thu May 22 17:33:57 2008 New Revision: 55132 Modified: pypy/branch/win32port/pypy/rpython/tool/test/test_c.py Log: Correct test for win32 platform Modified: pypy/branch/win32port/pypy/rpython/tool/test/test_c.py ============================================================================== --- pypy/branch/win32port/pypy/rpython/tool/test/test_c.py (original) +++ pypy/branch/win32port/pypy/rpython/tool/test/test_c.py Thu May 22 17:33:57 2008 @@ -22,10 +22,25 @@ compiler = ccompiler.new_compiler() c_file = udir.join('rffilib.c') c_file.write(c_source) - compiler.compile([str(c_file)], output_dir='/') - compiler.link_shared_lib([str(udir.join('rffilib.o'))], - 'rffi', output_dir=str(udir)) - cls.lib = ctypes.CDLL(str(udir.join('librffi.so'))) + + if sys.platform == 'win32': + ccflags = [] + o_file = 'rffilib.obj' + so_file = 'rffi.dll' + else: + ccflags = ['-fPIC'] + o_file = 'rffilib.o' + so_file = 'librffi.so' + + rootdir = os.path.splitdrive(str(udir))[0] + '/' + compiler.compile([str(c_file)], output_dir=rootdir, + extra_preargs=ccflags) + + compiler.link_shared_lib([str(udir.join(o_file))], + 'rffi', output_dir=str(udir), + export_symbols = ['int_int_to_struct_p', + 'int_to_void_p']) + cls.lib = ctypes.CDLL(str(udir.join(so_file))) def test_basic(self): assert self.lib From afa at codespeak.net Thu May 22 19:04:20 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Thu, 22 May 2008 19:04:20 +0200 (CEST) Subject: [pypy-svn] r55133 - in pypy/dist/pypy: config lib lib/_ctypes module/_rawffi module/_rawffi/test module/signal module/thread rlib rlib/test rpython/module/test rpython/tool rpython/tool/test translator/c translator/c/src translator/c/test translator/goal translator/goal/test2 Message-ID: <20080522170420.4FCEB168472@codespeak.net> Author: afa Date: Thu May 22 19:04:13 2008 New Revision: 55133 Added: pypy/dist/pypy/lib/_subprocess.py - copied unchanged from r55132, pypy/branch/win32port/pypy/lib/_subprocess.py pypy/dist/pypy/lib/msvcrt.py - copied unchanged from r55132, pypy/branch/win32port/pypy/lib/msvcrt.py pypy/dist/pypy/rpython/module/test/test_ll_os_environ.py - copied unchanged from r55132, pypy/branch/win32port/pypy/rpython/module/test/test_ll_os_environ.py Modified: pypy/dist/pypy/config/pypyoption.py pypy/dist/pypy/lib/_ctypes/builtin.py pypy/dist/pypy/module/_rawffi/__init__.py pypy/dist/pypy/module/_rawffi/interp_rawffi.py pypy/dist/pypy/module/_rawffi/test/test__rawffi.py pypy/dist/pypy/module/signal/interp_signal.py pypy/dist/pypy/module/thread/ll_thread.py pypy/dist/pypy/rlib/getnameinfo.py pypy/dist/pypy/rlib/libffi.py pypy/dist/pypy/rlib/rmmap.py pypy/dist/pypy/rlib/rpoll.py pypy/dist/pypy/rlib/rsocket.py pypy/dist/pypy/rlib/rwin32.py pypy/dist/pypy/rlib/test/test_libffi.py pypy/dist/pypy/rlib/test/test_rmmap.py pypy/dist/pypy/rlib/test/test_rpoll.py pypy/dist/pypy/rpython/tool/rffi_platform.py pypy/dist/pypy/rpython/tool/test/test_c.py pypy/dist/pypy/translator/c/genc.py pypy/dist/pypy/translator/c/src/instrument.h pypy/dist/pypy/translator/c/src/thread.h pypy/dist/pypy/translator/c/src/thread_nt.h pypy/dist/pypy/translator/c/test/test_extfunc.py pypy/dist/pypy/translator/c/test/test_newgc.py pypy/dist/pypy/translator/c/test/test_standalone.py pypy/dist/pypy/translator/goal/nanos.py pypy/dist/pypy/translator/goal/test2/test_nanos.py Log: Merge of the win32port branch: Port various modules to the win32 platform. _rawffi, ctypes, socket, select, signal now translate and (seem to) work on windows. They are now included in the --allworkingmodules. Outside the win32-specific changes, some modifications may have an impact on other platforms. It's perfectly possible that I broke something there. At least the pypy-c translation completes on Linux. These changes are: - r55127: cleanup sys.modules after importing nanos, to prevent inclusion of all os.pyc as a frozen module inside pypy-c. - r55055: added _rawffi.get_libc() which loads the same msvcrt as the one used by pypy-c. - r54947: remove Python.h dependency from pypy's src/thread.h. - r54946: CConfig.configure() adds the separate module files when compiling the sample program - r54928: Allow compilation of files residing outside the target directory. They are copied into our working dir, and compiled there. Modified: pypy/dist/pypy/config/pypyoption.py ============================================================================== --- pypy/dist/pypy/config/pypyoption.py (original) +++ pypy/dist/pypy/config/pypyoption.py Thu May 22 19:04:13 2008 @@ -37,12 +37,6 @@ del working_modules["_minimal_curses"] # modules currently missing explicit windows support del working_modules["signal"] - del working_modules["_rawffi"] - # modules with broken windows support - del working_modules["mmap"] # MLS - Added 5/11/08 - broken - del working_modules["_socket"] # MLS - Added 5/11/08 - broken - del working_modules["select"] # MLS - Added 5/11/08 - broken - module_dependencies = {} Modified: pypy/dist/pypy/lib/_ctypes/builtin.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/builtin.py (original) +++ pypy/dist/pypy/lib/_ctypes/builtin.py Thu May 22 19:04:13 2008 @@ -5,8 +5,8 @@ encoding = 'ascii' errors = 'strict' -_memmove_addr = ('memmove', _rawffi.libc_name) -_memset_addr = ('memset', _rawffi.libc_name) +_memmove_addr = _rawffi.get_libc().getaddressindll('memmove') +_memset_addr = _rawffi.get_libc().getaddressindll('memset') def _string_at_addr(addr, lgt): # address here can be almost anything Modified: pypy/dist/pypy/module/_rawffi/__init__.py ============================================================================== --- pypy/dist/pypy/module/_rawffi/__init__.py (original) +++ pypy/dist/pypy/module/_rawffi/__init__.py Thu May 22 19:04:13 2008 @@ -25,6 +25,7 @@ 'charp2rawstring' : 'interp_rawffi.charp2rawstring', 'CallbackPtr' : 'callback.W_CallbackPtr', '_num_of_allocated_objects' : 'tracker.num_of_allocated_objects', + 'get_libc' : 'interp_rawffi.get_libc', } appleveldefs = { @@ -44,10 +45,6 @@ ]: if hasattr(libffi, name): Module.interpleveldefs[name] = "space.wrap(%r)" % getattr(libffi, name) - - # Name of C runtime library - from pypy.rpython.lltypesystem.ll2ctypes import get_libc_name - Module.interpleveldefs['libc_name'] = "space.wrap(%r)" % get_libc_name() super(Module, cls).buildloaders() buildloaders = classmethod(buildloaders) Modified: pypy/dist/pypy/module/_rawffi/interp_rawffi.py ============================================================================== --- pypy/dist/pypy/module/_rawffi/interp_rawffi.py (original) +++ pypy/dist/pypy/module/_rawffi/interp_rawffi.py Thu May 22 19:04:13 2008 @@ -468,3 +468,9 @@ raise OperationError(space.w_WindowsError, space.wrap(hresult)) return space.wrap(hresult) check_HRESULT.unwrap_spec = [ObjSpace, int] + +def get_libc(space): + try: + return space.wrap(W_CDLL(space, get_libc_name())) + except OSError, e: + raise wrap_oserror(space, e) Modified: pypy/dist/pypy/module/_rawffi/test/test__rawffi.py ============================================================================== --- pypy/dist/pypy/module/_rawffi/test/test__rawffi.py (original) +++ pypy/dist/pypy/module/_rawffi/test/test__rawffi.py Thu May 22 19:04:13 2008 @@ -180,9 +180,13 @@ import _rawffi _rawffi.CDLL(self.libc_name) + def test_libc_load(self): + import _rawffi + _rawffi.get_libc() + def test_getattr(self): import _rawffi - libc = _rawffi.CDLL(self.libc_name) + libc = _rawffi.get_libc() func = libc.ptr('rand', [], 'i') assert libc.ptr('rand', [], 'i') is func # caching assert libc.ptr('rand', [], 'l') is not func @@ -292,7 +296,7 @@ def test_time(self): import _rawffi - libc = _rawffi.CDLL(self.libc_name) + libc = _rawffi.get_libc() time = libc.ptr('time', ['z'], 'l') # 'z' instead of 'P' just for test arg = _rawffi.Array('P')(1) arg[0] = 0 @@ -306,7 +310,7 @@ import _rawffi struct_type = _rawffi.Structure([('tv_sec', 'l'), ('tv_usec', 'l')]) structure = struct_type() - libc = _rawffi.CDLL(self.libc_name) + libc = _rawffi.get_libc() gettimeofday = libc.ptr('gettimeofday', ['P', 'P'], 'i') arg1 = structure.byptr() @@ -341,7 +345,7 @@ ("tm_wday", 'i'), ("tm_yday", 'i'), ("tm_isdst", 'i')]) - libc = _rawffi.CDLL(self.libc_name) + libc = _rawffi.get_libc() gmtime = libc.ptr('gmtime', ['P'], 'P') arg = x.byptr() @@ -452,7 +456,7 @@ skip("FIXME: compare actually receives a pair of int**") import _rawffi import struct - libc = _rawffi.CDLL(self.libc_name) + libc = _rawffi.get_libc() ll_to_sort = _rawffi.Array('i')(4) for i in range(4): ll_to_sort[i] = 4-i Modified: pypy/dist/pypy/module/signal/interp_signal.py ============================================================================== --- pypy/dist/pypy/module/signal/interp_signal.py (original) +++ pypy/dist/pypy/module/signal/interp_signal.py Thu May 22 19:04:13 2008 @@ -21,7 +21,8 @@ eci = ExternalCompilationInfo( includes = ['stdlib.h', 'src/signals.h'], separate_module_sources = ['#include '], - include_dirs = [str(py.path.local(autopath.pypydir).join('translator', 'c'))] + include_dirs = [str(py.path.local(autopath.pypydir).join('translator', 'c'))], + export_symbols = ['pypysig_poll'], ) def external(name, args, result, **kwds): Modified: pypy/dist/pypy/module/thread/ll_thread.py ============================================================================== --- pypy/dist/pypy/module/thread/ll_thread.py (original) +++ pypy/dist/pypy/module/thread/ll_thread.py Thu May 22 19:04:13 2008 @@ -6,7 +6,7 @@ from pypy.rpython.annlowlevel import cast_instance_to_base_ptr from pypy.translator.tool.cbuild import ExternalCompilationInfo from pypy.rpython.lltypesystem import llmemory -import thread, py +import thread, py, os from pypy.rpython.extregistry import ExtRegistryEntry from pypy.annotation import model as annmodel from pypy.rpython.lltypesystem.lltype import typeOf @@ -18,14 +18,13 @@ error = thread.error eci = ExternalCompilationInfo( - includes = ['unistd.h', 'src/thread.h'], - separate_module_sources=[''' - #include - #include - #include - '''], + includes = ['src/thread.h'], + separate_module_sources = [''], include_dirs = [str(py.path.local(autopath.pypydir).join('translator', 'c')), - python_inc] + python_inc], + export_symbols = ['RPyThreadGetIdent', 'RPyThreadLockInit', + 'RPyThreadAcquireLock', 'RPyThreadReleaseLock', + 'RPyThreadFusedReleaseAcquireLock',] ) def llexternal(name, args, result, **kwds): Modified: pypy/dist/pypy/rlib/getnameinfo.py ============================================================================== --- pypy/dist/pypy/rlib/getnameinfo.py (original) +++ pypy/dist/pypy/rlib/getnameinfo.py Thu May 22 19:04:13 2008 @@ -24,7 +24,7 @@ if sp: serv = rffi.charp2str(sp.c_s_name) else: - serv = "%d" % _c.ntohs(sin_port) + serv = "%d" % r_uint(_c.ntohs(sin_port)) return serv Modified: pypy/dist/pypy/rlib/libffi.py ============================================================================== --- pypy/dist/pypy/rlib/libffi.py (original) +++ pypy/dist/pypy/rlib/libffi.py Thu May 22 19:04:13 2008 @@ -37,15 +37,31 @@ else: libffidir = py.path.local(pypydir).join('translator', 'c', 'src', 'libffi_msvc') eci = ExternalCompilationInfo( + pre_include_lines = ['#define _WIN32_WINNT 0x501'], includes = ['ffi.h', 'windows.h'], libraries = ['kernel32'], include_dirs = [libffidir], + separate_module_sources = [''' + #include + + /* Get the module where the "fopen" function resides in */ + HANDLE get_libc_handle() { + MEMORY_BASIC_INFORMATION mi; + memset(&mi, 0, sizeof(mi)); + + if( !VirtualQueryEx(GetCurrentProcess(), &fopen, &mi, sizeof(mi)) ) + return 0; + + return (HMODULE)mi.AllocationBase; + } + '''], separate_module_files = [libffidir.join('ffi.c'), libffidir.join('prep_cif.c'), libffidir.join('win32.c'), libffidir.join('pypy_ffi.c'), ], - export_symbols = ['ffi_call', 'ffi_prep_cif', 'ffi_prep_closure'], + export_symbols = ['ffi_call', 'ffi_prep_cif', 'ffi_prep_closure', + 'get_libc_handle'], ) FFI_TYPE_P = lltype.Ptr(lltype.ForwardReference()) @@ -193,6 +209,9 @@ # XXX rffi.cast here... return res + def get_libc_name(): + return 'libc.so.6' + if _MS_WINDOWS: def dlopen(name): res = rwin32.LoadLibrary(name) @@ -218,6 +237,12 @@ FormatError = rwin32.FormatError LoadLibrary = rwin32.LoadLibrary + get_libc_handle = external('get_libc_handle', [], rwin32.HANDLE) + + def get_libc_name(): + return rwin32.GetModuleFileName(get_libc_handle()) + + FFI_OK = cConfig.FFI_OK FFI_BAD_TYPEDEF = cConfig.FFI_BAD_TYPEDEF FFI_DEFAULT_ABI = rffi.cast(rffi.USHORT, cConfig.FFI_DEFAULT_ABI) @@ -518,3 +543,4 @@ def getaddressindll(self, name): return dlsym(self.lib, name) + Modified: pypy/dist/pypy/rlib/rmmap.py ============================================================================== --- pypy/dist/pypy/rlib/rmmap.py (original) +++ pypy/dist/pypy/rlib/rmmap.py Thu May 22 19:04:13 2008 @@ -38,21 +38,7 @@ size_t = rffi_platform.SimpleType("size_t", rffi.LONG) off_t = rffi_platform.SimpleType("off_t", rffi.LONG) if _MS_WINDOWS: - DWORD_PTR = rffi_platform.SimpleType("DWORD_PTR", rffi.LONG) - WORD = rffi_platform.SimpleType("WORD", rffi.UINT) - DWORD = rffi_platform.SimpleType("DWORD", rffi.ULONG) - BOOL = rffi_platform.SimpleType("BOOL", rffi.LONG) - INT = rffi_platform.SimpleType("INT", rffi.INT) - LONG = rffi_platform.SimpleType("LONG", rffi.LONG) - PLONG = rffi_platform.SimpleType("PLONG", rffi.LONGP) - LPVOID = rffi_platform.SimpleType("LPVOID", rffi.INTP) - LPCVOID = rffi_platform.SimpleType("LPCVOID", rffi.VOIDP) - HANDLE = rffi_platform.SimpleType("HANDLE", rffi.VOIDP) - LPHANDLE = rffi_platform.SimpleType("LPHANDLE", rffi.CCHARPP) - LPCTSTR = rffi_platform.SimpleType("LPCTSTR", rffi.CCHARP) - LPDWORD = rffi_platform.SimpleType("LPDWORD", rffi.INTP) LPSECURITY_ATTRIBUTES = rffi_platform.SimpleType("LPSECURITY_ATTRIBUTES", rffi.CCHARP) - SIZE_T = rffi_platform.SimpleType("SIZE_T", rffi.SIZE_T) constants = {} if _POSIX: @@ -82,6 +68,11 @@ for name in constant_names: setattr(CConfig, name, rffi_platform.ConstantInteger(name)) + from pypy.rlib.rwin32 import HANDLE, LPHANDLE + from pypy.rlib.rwin32 import DWORD, WORD, DWORD_PTR, LPDWORD + from pypy.rlib.rwin32 import BOOL, LPVOID, LPCVOID, LPCTSTR, SIZE_T + from pypy.rlib.rwin32 import INT, LONG, PLONG + # export the constants inside and outside. see __init__.py cConfig = rffi_platform.configure(CConfig) constants.update(cConfig) Modified: pypy/dist/pypy/rlib/rpoll.py ============================================================================== --- pypy/dist/pypy/rlib/rpoll.py (original) +++ pypy/dist/pypy/rlib/rpoll.py Thu May 22 19:04:13 2008 @@ -8,6 +8,7 @@ import os from pypy.rlib import _rsocket_rffi as _c from pypy.rpython.lltypesystem import lltype, rffi +from pypy.rlib.rarithmetic import intmask, r_uint # ____________________________________________________________ # events @@ -121,7 +122,7 @@ if ret == _c.WSA_WAIT_TIMEOUT: return [] - if ret == _c.WSA_WAIT_FAILED: + if ret == r_uint(_c.WSA_WAIT_FAILED): raise PollError(_c.geterrno()) retval = [] Modified: pypy/dist/pypy/rlib/rsocket.py ============================================================================== --- pypy/dist/pypy/rlib/rsocket.py (original) +++ pypy/dist/pypy/rlib/rsocket.py Thu May 22 19:04:13 2008 @@ -153,8 +153,7 @@ flags=AI_PASSIVE, address_to_fill=result) if len(info) > 1: - raise RSocketError("wildcard resolved to " - "multiple addresses") + raise RSocketError("wildcard resolved to multiple addresses") return info[0][4] # IPv4 also supports the special name "". Modified: pypy/dist/pypy/rlib/rwin32.py ============================================================================== --- pypy/dist/pypy/rlib/rwin32.py (original) +++ pypy/dist/pypy/rlib/rwin32.py Thu May 22 19:04:13 2008 @@ -23,11 +23,20 @@ _compilation_info_ = eci if WIN32: + DWORD_PTR = rffi_platform.SimpleType("DWORD_PTR", rffi.LONG) + WORD = rffi_platform.SimpleType("WORD", rffi.UINT) DWORD = rffi_platform.SimpleType("DWORD", rffi.UINT) BOOL = rffi_platform.SimpleType("BOOL", rffi.LONG) - HRESULT = rffi_platform.SimpleType("HRESULT", rffi.LONG) + INT = rffi_platform.SimpleType("INT", rffi.INT) + LONG = rffi_platform.SimpleType("LONG", rffi.LONG) + PLONG = rffi_platform.SimpleType("PLONG", rffi.LONGP) + LPVOID = rffi_platform.SimpleType("LPVOID", rffi.INTP) + LPCVOID = rffi_platform.SimpleType("LPCVOID", rffi.VOIDP) + LPCTSTR = rffi_platform.SimpleType("LPCTSTR", rffi.CCHARP) + LPDWORD = rffi_platform.SimpleType("LPDWORD", rffi.INTP) + SIZE_T = rffi_platform.SimpleType("SIZE_T", rffi.SIZE_T) - HANDLE = rffi_platform.SimpleType("HANDLE", rffi.VOIDP) + HRESULT = rffi_platform.SimpleType("HRESULT", rffi.LONG) HLOCAL = rffi_platform.SimpleType("HLOCAL", rffi.VOIDP) DEFAULT_LANGUAGE = rffi_platform.ConstantInteger( @@ -45,6 +54,10 @@ return rffi.llexternal(name, args, result, compilation_info=eci, calling_conv='win') if WIN32: + HANDLE = rffi.ULONG + LPHANDLE = rffi.CArrayPtr(HANDLE) + HMODULE = HANDLE + GetLastError = winexternal('GetLastError', [], DWORD) LoadLibrary = winexternal('LoadLibraryA', [rffi.CCHARP], rffi.VOIDP) @@ -83,4 +96,16 @@ def FAILED(hr): return rffi.cast(HRESULT, hr) < 0 - + + _GetModuleFileName = winexternal('GetModuleFileNameA', + [HMODULE, rffi.CCHARP, DWORD], + DWORD) + + def GetModuleFileName(module): + size = 255 # MAX_PATH + buf = lltype.malloc(rffi.CCHARP.TO, size, flavor='raw') + res = _GetModuleFileName(module, buf, size) + if not res: + return '' + else: + return ''.join([buf[i] for i in range(res)]) Modified: pypy/dist/pypy/rlib/test/test_libffi.py ============================================================================== --- pypy/dist/pypy/rlib/test/test_libffi.py (original) +++ pypy/dist/pypy/rlib/test/test_libffi.py Thu May 22 19:04:13 2008 @@ -360,3 +360,11 @@ del lib assert not ALLOCATED + +class TestWin32Handles: + def test_get_libc_handle(self): + handle = get_libc_handle() + print get_libc_name() + print hex(handle) + assert handle != 0 + assert handle % 0x1000 == 0 Modified: pypy/dist/pypy/rlib/test/test_rmmap.py ============================================================================== --- pypy/dist/pypy/rlib/test/test_rmmap.py (original) +++ pypy/dist/pypy/rlib/test/test_rmmap.py Thu May 22 19:04:13 2008 @@ -371,3 +371,14 @@ interpret(func, [f.fileno()]) f.close() + + def test_translated(self): + from pypy.translator.c.test.test_genc import compile + + def func(no): + m = mmap.mmap(no, 1) + r = m.read_byte() + m.close() + return r + + compile(func, [int]) Modified: pypy/dist/pypy/rlib/test/test_rpoll.py ============================================================================== --- pypy/dist/pypy/rlib/test/test_rpoll.py (original) +++ pypy/dist/pypy/rlib/test/test_rpoll.py Thu May 22 19:04:13 2008 @@ -47,3 +47,11 @@ cli.close() servconn.close() serv.close() + +def test_translate(): + from pypy.translator.c.test.test_genc import compile + + def func(): + poll({}) + + compile(func, []) Modified: pypy/dist/pypy/rpython/tool/rffi_platform.py ============================================================================== --- pypy/dist/pypy/rpython/tool/rffi_platform.py (original) +++ pypy/dist/pypy/rpython/tool/rffi_platform.py Thu May 22 19:04:13 2008 @@ -537,7 +537,9 @@ """ def run_example_code(filepath, eci): - output = build_executable_cache([filepath], eci) + eci = eci.convert_sources_to_files(being_main=True) + files = [filepath] + [py.path.local(f) for f in eci.separate_module_files] + output = build_executable_cache(files, eci) section = None for line in output.splitlines(): line = line.strip() Modified: pypy/dist/pypy/rpython/tool/test/test_c.py ============================================================================== --- pypy/dist/pypy/rpython/tool/test/test_c.py (original) +++ pypy/dist/pypy/rpython/tool/test/test_c.py Thu May 22 19:04:13 2008 @@ -22,10 +22,25 @@ compiler = ccompiler.new_compiler() c_file = udir.join('rffilib.c') c_file.write(c_source) - compiler.compile([str(c_file)], output_dir='/') - compiler.link_shared_lib([str(udir.join('rffilib.o'))], - 'rffi', output_dir=str(udir)) - cls.lib = ctypes.CDLL(str(udir.join('librffi.so'))) + + if sys.platform == 'win32': + ccflags = [] + o_file = 'rffilib.obj' + so_file = 'rffi.dll' + else: + ccflags = ['-fPIC'] + o_file = 'rffilib.o' + so_file = 'librffi.so' + + rootdir = os.path.splitdrive(str(udir))[0] + '/' + compiler.compile([str(c_file)], output_dir=rootdir, + extra_preargs=ccflags) + + compiler.link_shared_lib([str(udir.join(o_file))], + 'rffi', output_dir=str(udir), + export_symbols = ['int_int_to_struct_p', + 'int_to_void_p']) + cls.lib = ctypes.CDLL(str(udir.join(so_file))) def test_basic(self): assert self.lib Modified: pypy/dist/pypy/translator/c/genc.py ============================================================================== --- pypy/dist/pypy/translator/c/genc.py (original) +++ pypy/dist/pypy/translator/c/genc.py Thu May 22 19:04:13 2008 @@ -304,8 +304,18 @@ if profopt is not None and not self.config.translation.noprofopt: profbased = (ProfOpt, profopt) + # Copy extrafiles to target directory, if needed + extrafiles = [] + for fn in self.extrafiles: + fn = py.path.local(fn) + if not fn.relto(udir): + newname = self.targetdir.join(fn.basename) + fn.copy(newname) + fn = newname + extrafiles.append(fn) + return CCompiler( - [self.c_source_filename] + self.extrafiles, + [self.c_source_filename] + extrafiles, self.eci, compiler_exe = cc, profbased = profbased) def compile(self): @@ -366,6 +376,8 @@ else: assert fn.dirpath().dirpath() == udir name = '../' + fn.relto(udir) + + name = name.replace("\\", "/") cfiles.append(name) if self.config.translation.gcrootfinder == "asmgcc": ofiles.append(name[:-2] + '.s') Modified: pypy/dist/pypy/translator/c/src/instrument.h ============================================================================== --- pypy/dist/pypy/translator/c/src/instrument.h (original) +++ pypy/dist/pypy/translator/c/src/instrument.h Thu May 22 19:04:13 2008 @@ -9,10 +9,14 @@ #include #include #include +#ifndef WIN32 #include #include #include #include +#else +#include +#endif typedef unsigned long instrument_count_t; @@ -22,18 +26,33 @@ char *fname = getenv("_INSTRUMENT_COUNTERS"); if (fname) { int fd; +#ifdef WIN32 + HANDLE map_handle; + HANDLE file_handle; +#endif void *buf; size_t sz = sizeof(instrument_count_t)*INSTRUMENT_NCOUNTER; fd = open(fname, O_CREAT|O_TRUNC|O_RDWR, 0744); if (sz > 0) { lseek(fd, sz-1, SEEK_SET); write(fd, "", 1); +#ifndef WIN32 buf = mmap(NULL, sz, PROT_WRITE|PROT_READ, MAP_SHARED, fd, 0); if (buf == MAP_FAILED) { fprintf(stderr, "mapping instrument counters file failed\n"); abort(); } +#else + file_handle = (HANDLE)_get_osfhandle(fd); + map_handle = CreateFileMapping(file_handle, NULL, PAGE_READWRITE, + 0, sz, ""); + buf = MapViewOfFile(map_handle, FILE_MAP_WRITE, 0, 0, 0); + if (buf == 0) { + fprintf(stderr, "mapping instrument counters file failed\n"); + abort(); + } +#endif _instrument_counters = (instrument_count_t *)buf; } } Modified: pypy/dist/pypy/translator/c/src/thread.h ============================================================================== --- pypy/dist/pypy/translator/c/src/thread.h (original) +++ pypy/dist/pypy/translator/c/src/thread.h Thu May 22 19:04:13 2008 @@ -3,7 +3,13 @@ #ifndef __PYPY_THREAD_H #define __PYPY_THREAD_H -#include "Python.h" +#include + +#ifdef _WIN32 +#include "thread_nt.h" +#else + +#include #ifndef _POSIX_THREADS /* This means pthreads are not implemented in libc headers, hence the macro @@ -18,9 +24,7 @@ #include "thread_pthread.h" #endif -#ifdef NT_THREADS -#include "thread_nt.h" -#endif +#endif /* !_WIN32 */ #ifdef USE___THREAD Modified: pypy/dist/pypy/translator/c/src/thread_nt.h ============================================================================== --- pypy/dist/pypy/translator/c/src/thread_nt.h (original) +++ pypy/dist/pypy/translator/c/src/thread_nt.h Thu May 22 19:04:13 2008 @@ -19,11 +19,6 @@ * Thread support. */ -/* - * Return the thread Id instead of an handle. The Id is said to uniquely - identify the thread in the system - */ -#define RPyThreadGetIdent GetCurrentThreadId #define RPyOpaque_INITEXPR_ThreadLock { 0, 0, NULL } typedef struct { @@ -54,6 +49,15 @@ #ifndef PYPY_NOT_MAIN_FILE +/* + * Return the thread Id instead of an handle. The Id is said to uniquely + identify the thread in the system + */ +int RPyThreadGetIdent() +{ + return GetCurrentThreadId(); +} + static int bootstrap(void *call) { @@ -201,7 +205,10 @@ /************************************************************/ -#define RPyThreadLockInit(lock) InitializeNonRecursiveMutex(lock) +int RPyThreadLockInit(struct RPyOpaque_ThreadLock * lock) +{ + return InitializeNonRecursiveMutex(lock); +} void RPyOpaqueDealloc_ThreadLock(struct RPyOpaque_ThreadLock *lock) { Modified: pypy/dist/pypy/translator/c/test/test_extfunc.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_extfunc.py (original) +++ pypy/dist/pypy/translator/c/test/test_extfunc.py Thu May 22 19:04:13 2008 @@ -657,9 +657,8 @@ elif hasattr(os, 'waitpid'): # windows has no fork but some waitpid to be emulated def test_waitpid(): + prog = str(sys.executable) def does_stuff(): - prog = sys.executable - prog = str(prog) args = [prog] # args = [prog, '-c', '"import os;os._exit(4)"'] # note that the above variant creates a bad array Modified: pypy/dist/pypy/translator/c/test/test_newgc.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_newgc.py (original) +++ pypy/dist/pypy/translator/c/test/test_newgc.py Thu May 22 19:04:13 2008 @@ -19,13 +19,14 @@ from pypy.config.pypyoption import get_pypy_config config = get_pypy_config(translating=True) config.translation.gc = gcpolicy + config.translation.countmallocs = True if t is None: t = TranslationContext(config=config) if inputtypes is not None: t.buildannotator().build_types(fn, inputtypes) t.buildrtyper().specialize() builder = genc.CExtModuleBuilder(t, fn, config=config) - builder.generate_source(defines={'COUNT_OP_MALLOCS': 1}) + builder.generate_source() builder.compile() if conftest.option.view: t.view() @@ -838,11 +839,13 @@ def test_callback_with_collect(self): from pypy.rlib.libffi import ffi_type_pointer, cast_type_to_ffitype,\ CDLL, ffi_type_void, CallbackFuncPtr, ffi_type_sint - from pypy.rpython.lltypesystem import rffi + from pypy.rpython.lltypesystem import rffi, ll2ctypes from pypy.rlib import rgc import gc slong = cast_type_to_ffitype(rffi.LONG) + libc_name = ll2ctypes.get_libc_name() + def callback(ll_args, ll_res, stuff): gc.collect() p_a1 = rffi.cast(rffi.VOIDPP, ll_args[0])[0] @@ -856,7 +859,7 @@ res[0] = -1 def f(): - libc = CDLL('libc.so.6') + libc = CDLL(libc_name) qsort = libc.getpointer('qsort', [ffi_type_pointer, slong, slong, ffi_type_pointer], ffi_type_void) Modified: pypy/dist/pypy/translator/c/test/test_standalone.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_standalone.py (original) +++ pypy/dist/pypy/translator/c/test/test_standalone.py Thu May 22 19:04:13 2008 @@ -4,9 +4,10 @@ from pypy.rlib.rarithmetic import r_longlong from pypy.translator.translator import TranslationContext from pypy.translator.backendopt import all -from pypy.translator.c.genc import CStandaloneBuilder +from pypy.translator.c.genc import CStandaloneBuilder, ExternalCompilationInfo from pypy.annotation.listdef import s_list_of_strings from pypy.tool.udir import udir +from pypy.tool.autopath import pypydir def test_hello_world(): @@ -54,8 +55,6 @@ # gives the strings unquoted in the list def test_counters(): - if sys.platform == 'win32': - py.test.skip("instrument counters support is unix only for now") from pypy.rpython.lltypesystem import lltype from pypy.rpython.lltypesystem.lloperation import llop def entry_point(argv): @@ -138,8 +137,6 @@ assert map(float, data.split()) == [0.0, 0.0] def test_profopt(): - if sys.platform == 'win32': - py.test.skip("instrumentation support is unix only for now") def add(a,b): return a + b - b + b - b + b - b + b - b + b - b + b - b + b def entry_point(argv): @@ -190,3 +187,42 @@ cbuilder.compile() data = cbuilder.cmdexec('hi there') assert data.strip() == "OK" + +def test_separate_files(): + # One file in translator/c/src + fname = py.path.local(pypydir).join( + 'translator', 'c', 'src', 'll_strtod.h') + + # One file in (another) subdir of the temp directory + dirname = udir.join("test_dir").ensure(dir=1) + fname2 = dirname.join("test_genc.c") + fname2.write(""" + void f() { + LL_strtod_formatd("%5f", 12.3); + }""") + + files = [fname, fname2] + + def entry_point(argv): + return 0 + + t = TranslationContext() + t.buildannotator().build_types(entry_point, [s_list_of_strings]) + t.buildrtyper().specialize() + + cbuilder = CStandaloneBuilder(t, entry_point, t.config) + cbuilder.eci = cbuilder.eci.merge( + ExternalCompilationInfo(separate_module_files=files)) + cbuilder.generate_source() + + makefile = udir.join(cbuilder.modulename, 'Makefile').read() + + # generated files are compiled in the same directory + assert " ../test_dir/test_genc.c" in makefile + assert " ../test_dir/test_genc.o" in makefile + + # but files from pypy source dir must be copied + assert "translator/c/src" not in makefile + assert " ll_strtod.h" in makefile + assert " ll_strtod.o" in makefile + Modified: pypy/dist/pypy/translator/goal/nanos.py ============================================================================== --- pypy/dist/pypy/translator/goal/nanos.py (original) +++ pypy/dist/pypy/translator/goal/nanos.py Thu May 22 19:04:13 2008 @@ -29,17 +29,25 @@ import os app_os_path = applevel(r''' - # NOT_RPYTHON from os.path import dirname, join, abspath, isfile, islink ''', filename=__file__) app_os = applevel(r''' # NOT_RPYTHON + import sys + sysmodules = sys.modules.keys() + from os import sep, pathsep, getenv, name, fdopen try: from os import readlink except ImportError: pass + + # restore the previous list of loaded modules + for name in sys.modules.keys(): + if name not in sysmodules: + del sys.modules[name] + del sys ''', filename=__file__) def getenv(space, w_name): Modified: pypy/dist/pypy/translator/goal/test2/test_nanos.py ============================================================================== --- pypy/dist/pypy/translator/goal/test2/test_nanos.py (original) +++ pypy/dist/pypy/translator/goal/test2/test_nanos.py Thu May 22 19:04:13 2008 @@ -17,4 +17,10 @@ w_dict = space.newdict() space.exec_(open(filename).read(), w_dict, w_dict) entry_point = create_entry_point(space, w_dict) + + # check that 'os' is not in sys.modules + assert not space.is_true( + space.call_method(space.sys.get('modules'), + '__contains__', space.wrap('os'))) + entry_point(['', '-c', 'print 42']) From afa at codespeak.net Thu May 22 19:15:25 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Thu, 22 May 2008 19:15:25 +0200 (CEST) Subject: [pypy-svn] r55134 - in pypy/dist/pypy: lib rlib rpython/module/test Message-ID: <20080522171525.BBD1D168472@codespeak.net> Author: afa Date: Thu May 22 19:15:25 2008 New Revision: 55134 Modified: pypy/dist/pypy/lib/_subprocess.py (contents, props changed) pypy/dist/pypy/lib/msvcrt.py (contents, props changed) pypy/dist/pypy/rlib/rwin32.py (contents, props changed) pypy/dist/pypy/rpython/module/test/test_ll_os_environ.py (contents, props changed) Log: fixeol Modified: pypy/dist/pypy/lib/_subprocess.py ============================================================================== --- pypy/dist/pypy/lib/_subprocess.py (original) +++ pypy/dist/pypy/lib/_subprocess.py Thu May 22 19:15:25 2008 @@ -1,189 +1,189 @@ -""" -Support routines for subprocess module. -Currently, this extension module is only required when using the -subprocess module on Windows. -""" - - -# Declare external Win32 functions - -import ctypes - -_kernel32 = ctypes.WinDLL('kernel32') - -_CloseHandle = _kernel32.CloseHandle -_CloseHandle.argtypes = [ctypes.c_int] -_CloseHandle.restype = ctypes.c_int - -_CreatePipe = _kernel32.CreatePipe -_CreatePipe.argtypes = [ctypes.POINTER(ctypes.c_int), ctypes.POINTER(ctypes.c_int), - ctypes.c_void_p, ctypes.c_int] -_CreatePipe.restype = ctypes.c_int - -_GetCurrentProcess = _kernel32.GetCurrentProcess -_GetCurrentProcess.argtypes = [] -_GetCurrentProcess.restype = ctypes.c_int - -_DuplicateHandle = _kernel32.DuplicateHandle -_DuplicateHandle.argtypes = [ctypes.c_int, ctypes.c_int, ctypes.c_int, - ctypes.POINTER(ctypes.c_int), - ctypes.c_int, ctypes.c_int, ctypes.c_int] -_DuplicateHandle.restype = ctypes.c_int - -_WaitForSingleObject = _kernel32.WaitForSingleObject -_WaitForSingleObject.argtypes = [ctypes.c_int, ctypes.c_int] -_WaitForSingleObject.restype = ctypes.c_int - -_GetExitCodeProcess = _kernel32.GetExitCodeProcess -_GetExitCodeProcess.argtypes = [ctypes.c_int, ctypes.POINTER(ctypes.c_int)] -_GetExitCodeProcess.restype = ctypes.c_int - -_GetStdHandle = _kernel32.GetStdHandle -_GetStdHandle.argtypes = [ctypes.c_int] -_GetStdHandle.restype = ctypes.c_int - -class _STARTUPINFO(ctypes.Structure): - _fields_ = [('cb', ctypes.c_int), - ('lpReserved', ctypes.c_void_p), - ('lpDesktop', ctypes.c_char_p), - ('lpTitle', ctypes.c_char_p), - ('dwX', ctypes.c_int), - ('dwY', ctypes.c_int), - ('dwXSize', ctypes.c_int), - ('dwYSize', ctypes.c_int), - ('dwXCountChars', ctypes.c_int), - ('dwYCountChars', ctypes.c_int), - ("dwFillAttribute", ctypes.c_int), - ("dwFlags", ctypes.c_int), - ("wShowWindow", ctypes.c_short), - ("cbReserved2", ctypes.c_short), - ("lpReserved2", ctypes.c_void_p), - ("hStdInput", ctypes.c_int), - ("hStdOutput", ctypes.c_int), - ("hStdError", ctypes.c_int) - ] - -class _PROCESS_INFORMATION(ctypes.Structure): - _fields_ = [("hProcess", ctypes.c_int), - ("hThread", ctypes.c_int), - ("dwProcessID", ctypes.c_int), - ("dwThreadID", ctypes.c_int)] - -_CreateProcess = _kernel32.CreateProcessA -_CreateProcess.argtypes = [ctypes.c_char_p, ctypes.c_char_p, ctypes.c_void_p, ctypes.c_void_p, - ctypes.c_int, ctypes.c_int, ctypes.c_char_p, ctypes.c_char_p, - ctypes.POINTER(_STARTUPINFO), ctypes.POINTER(_PROCESS_INFORMATION)] -_CreateProcess.restype = ctypes.c_int - -del ctypes - -# Now the _subprocess module implementation - -from ctypes import c_int as _c_int, byref as _byref - -class _handle: - def __init__(self, handle): - self.handle = handle - - def __int__(self): - return self.handle - - def Detach(self): - handle, self.handle = self.handle, None - return handle - - def Close(self): - if self.handle not in (-1, None): - _CloseHandle(self.handle) - self.handle = None - -def CreatePipe(attributes, size): - read = _c_int() - write = _c_int() - - res = _CreatePipe(_byref(read), _byref(write), None, size) - - if not res: - raise WindowsError("Error") - - return _handle(read.value), _handle(write.value) - -def GetCurrentProcess(): - return _handle(_GetCurrentProcess()) - - -def DuplicateHandle(source_process, source, target_process, access, inherit, options=0): - target = _c_int() - - res = _DuplicateHandle(int(source_process), int(source), int(target_process), - _byref(target), - access, inherit, options) - - if not res: - raise WindowsError("Error") - - return _handle(target.value) -DUPLICATE_SAME_ACCESS = 2 - - -def CreateProcess(name, command_line, process_attr, thread_attr, - inherit, flags, env, start_dir, startup_info): - si = _STARTUPINFO() - si.dwFlags = startup_info.dwFlags - si.wShowWindow = getattr(startup_info, 'wShowWindow', 0) - if startup_info.hStdInput: - si.hStdInput = startup_info.hStdInput.handle - if startup_info.hStdOutput: - si.hStdOutput = startup_info.hStdOutput.handle - if startup_info.hStdError: - si.hStdError = startup_info.hStdError.handle - - pi = _PROCESS_INFORMATION() - - if env is not None: - envbuf = "" - for k, v in env.iteritems(): - envbuf += "%s=%s\0" % (k, v) - envbuf += '\0' - else: - envbuf = None - - res = _CreateProcess(name, command_line, None, None, inherit, flags, envbuf, - start_dir, _byref(si), _byref(pi)) - - if not res: - raise WindowsError("Error") - - return _handle(pi.hProcess), _handle(pi.hThread), pi.dwProcessID, pi.dwThreadID -STARTF_USESTDHANDLES = 0x100 - -def WaitForSingleObject(handle, milliseconds): - res = _WaitForSingleObject(handle.handle, milliseconds) - - if res < 0: - raise WindowsError("Error") - - return res -INFINITE = 0xffffffff -WAIT_OBJECT_0 = 0 - -def GetExitCodeProcess(handle): - code = _c_int() - - res = _GetExitCodeProcess(handle.handle, _byref(code)) - - if not res: - raise WindowsError("Error") - - return code.value - -def GetStdHandle(stdhandle): - res = _GetStdHandle(stdhandle) - - if not res: - return None - else: - return res -STD_INPUT_HANDLE = -10 -STD_OUTPUT_HANDLE = -11 -STD_ERROR_HANDLE = -12 +""" +Support routines for subprocess module. +Currently, this extension module is only required when using the +subprocess module on Windows. +""" + + +# Declare external Win32 functions + +import ctypes + +_kernel32 = ctypes.WinDLL('kernel32') + +_CloseHandle = _kernel32.CloseHandle +_CloseHandle.argtypes = [ctypes.c_int] +_CloseHandle.restype = ctypes.c_int + +_CreatePipe = _kernel32.CreatePipe +_CreatePipe.argtypes = [ctypes.POINTER(ctypes.c_int), ctypes.POINTER(ctypes.c_int), + ctypes.c_void_p, ctypes.c_int] +_CreatePipe.restype = ctypes.c_int + +_GetCurrentProcess = _kernel32.GetCurrentProcess +_GetCurrentProcess.argtypes = [] +_GetCurrentProcess.restype = ctypes.c_int + +_DuplicateHandle = _kernel32.DuplicateHandle +_DuplicateHandle.argtypes = [ctypes.c_int, ctypes.c_int, ctypes.c_int, + ctypes.POINTER(ctypes.c_int), + ctypes.c_int, ctypes.c_int, ctypes.c_int] +_DuplicateHandle.restype = ctypes.c_int + +_WaitForSingleObject = _kernel32.WaitForSingleObject +_WaitForSingleObject.argtypes = [ctypes.c_int, ctypes.c_int] +_WaitForSingleObject.restype = ctypes.c_int + +_GetExitCodeProcess = _kernel32.GetExitCodeProcess +_GetExitCodeProcess.argtypes = [ctypes.c_int, ctypes.POINTER(ctypes.c_int)] +_GetExitCodeProcess.restype = ctypes.c_int + +_GetStdHandle = _kernel32.GetStdHandle +_GetStdHandle.argtypes = [ctypes.c_int] +_GetStdHandle.restype = ctypes.c_int + +class _STARTUPINFO(ctypes.Structure): + _fields_ = [('cb', ctypes.c_int), + ('lpReserved', ctypes.c_void_p), + ('lpDesktop', ctypes.c_char_p), + ('lpTitle', ctypes.c_char_p), + ('dwX', ctypes.c_int), + ('dwY', ctypes.c_int), + ('dwXSize', ctypes.c_int), + ('dwYSize', ctypes.c_int), + ('dwXCountChars', ctypes.c_int), + ('dwYCountChars', ctypes.c_int), + ("dwFillAttribute", ctypes.c_int), + ("dwFlags", ctypes.c_int), + ("wShowWindow", ctypes.c_short), + ("cbReserved2", ctypes.c_short), + ("lpReserved2", ctypes.c_void_p), + ("hStdInput", ctypes.c_int), + ("hStdOutput", ctypes.c_int), + ("hStdError", ctypes.c_int) + ] + +class _PROCESS_INFORMATION(ctypes.Structure): + _fields_ = [("hProcess", ctypes.c_int), + ("hThread", ctypes.c_int), + ("dwProcessID", ctypes.c_int), + ("dwThreadID", ctypes.c_int)] + +_CreateProcess = _kernel32.CreateProcessA +_CreateProcess.argtypes = [ctypes.c_char_p, ctypes.c_char_p, ctypes.c_void_p, ctypes.c_void_p, + ctypes.c_int, ctypes.c_int, ctypes.c_char_p, ctypes.c_char_p, + ctypes.POINTER(_STARTUPINFO), ctypes.POINTER(_PROCESS_INFORMATION)] +_CreateProcess.restype = ctypes.c_int + +del ctypes + +# Now the _subprocess module implementation + +from ctypes import c_int as _c_int, byref as _byref + +class _handle: + def __init__(self, handle): + self.handle = handle + + def __int__(self): + return self.handle + + def Detach(self): + handle, self.handle = self.handle, None + return handle + + def Close(self): + if self.handle not in (-1, None): + _CloseHandle(self.handle) + self.handle = None + +def CreatePipe(attributes, size): + read = _c_int() + write = _c_int() + + res = _CreatePipe(_byref(read), _byref(write), None, size) + + if not res: + raise WindowsError("Error") + + return _handle(read.value), _handle(write.value) + +def GetCurrentProcess(): + return _handle(_GetCurrentProcess()) + + +def DuplicateHandle(source_process, source, target_process, access, inherit, options=0): + target = _c_int() + + res = _DuplicateHandle(int(source_process), int(source), int(target_process), + _byref(target), + access, inherit, options) + + if not res: + raise WindowsError("Error") + + return _handle(target.value) +DUPLICATE_SAME_ACCESS = 2 + + +def CreateProcess(name, command_line, process_attr, thread_attr, + inherit, flags, env, start_dir, startup_info): + si = _STARTUPINFO() + si.dwFlags = startup_info.dwFlags + si.wShowWindow = getattr(startup_info, 'wShowWindow', 0) + if startup_info.hStdInput: + si.hStdInput = startup_info.hStdInput.handle + if startup_info.hStdOutput: + si.hStdOutput = startup_info.hStdOutput.handle + if startup_info.hStdError: + si.hStdError = startup_info.hStdError.handle + + pi = _PROCESS_INFORMATION() + + if env is not None: + envbuf = "" + for k, v in env.iteritems(): + envbuf += "%s=%s\0" % (k, v) + envbuf += '\0' + else: + envbuf = None + + res = _CreateProcess(name, command_line, None, None, inherit, flags, envbuf, + start_dir, _byref(si), _byref(pi)) + + if not res: + raise WindowsError("Error") + + return _handle(pi.hProcess), _handle(pi.hThread), pi.dwProcessID, pi.dwThreadID +STARTF_USESTDHANDLES = 0x100 + +def WaitForSingleObject(handle, milliseconds): + res = _WaitForSingleObject(handle.handle, milliseconds) + + if res < 0: + raise WindowsError("Error") + + return res +INFINITE = 0xffffffff +WAIT_OBJECT_0 = 0 + +def GetExitCodeProcess(handle): + code = _c_int() + + res = _GetExitCodeProcess(handle.handle, _byref(code)) + + if not res: + raise WindowsError("Error") + + return code.value + +def GetStdHandle(stdhandle): + res = _GetStdHandle(stdhandle) + + if not res: + return None + else: + return res +STD_INPUT_HANDLE = -10 +STD_OUTPUT_HANDLE = -11 +STD_ERROR_HANDLE = -12 Modified: pypy/dist/pypy/lib/msvcrt.py ============================================================================== --- pypy/dist/pypy/lib/msvcrt.py (original) +++ pypy/dist/pypy/lib/msvcrt.py Thu May 22 19:15:25 2008 @@ -1,22 +1,22 @@ -""" -Python interface to the Microsoft Visual C Runtime -Library, providing access to those non-portable, but -still useful routines. -""" - -# XXX incomplete: implemented only functions needed by subprocess.py - -import _rawffi -import ctypes - -_c = ctypes.CDLL('msvcrt', _rawffi.get_libc()) - -open_osfhandle = _c._open_osfhandle -open_osfhandle.argtypes = [ctypes.c_int, ctypes.c_int] -open_osfhandle.restype = ctypes.c_int - -get_osfhandle = _c._get_osfhandle -get_osfhandle.argtypes = [ctypes.c_int] -get_osfhandle.restype = ctypes.c_int - -del ctypes +""" +Python interface to the Microsoft Visual C Runtime +Library, providing access to those non-portable, but +still useful routines. +""" + +# XXX incomplete: implemented only functions needed by subprocess.py + +import _rawffi +import ctypes + +_c = ctypes.CDLL('msvcrt', _rawffi.get_libc()) + +open_osfhandle = _c._open_osfhandle +open_osfhandle.argtypes = [ctypes.c_int, ctypes.c_int] +open_osfhandle.restype = ctypes.c_int + +get_osfhandle = _c._get_osfhandle +get_osfhandle.argtypes = [ctypes.c_int] +get_osfhandle.restype = ctypes.c_int + +del ctypes Modified: pypy/dist/pypy/rlib/rwin32.py ============================================================================== --- pypy/dist/pypy/rlib/rwin32.py (original) +++ pypy/dist/pypy/rlib/rwin32.py Thu May 22 19:15:25 2008 @@ -1,111 +1,111 @@ -""" External functions accessing the win32 api. -Common types, functions from core win32 libraries, such as kernel32 -""" - -from pypy.rpython.tool import rffi_platform -from pypy.translator.tool.cbuild import ExternalCompilationInfo -from pypy.rpython.lltypesystem import lltype, rffi -import os - -# This module can be imported on any platform, -# but most symbols are not usable... -WIN32 = os.name == "nt" - -if WIN32: - eci = ExternalCompilationInfo( - includes = ['windows.h'], - libraries = ['kernel32'], - ) -else: - eci = ExternalCompilationInfo() - -class CConfig: - _compilation_info_ = eci - - if WIN32: - DWORD_PTR = rffi_platform.SimpleType("DWORD_PTR", rffi.LONG) - WORD = rffi_platform.SimpleType("WORD", rffi.UINT) - DWORD = rffi_platform.SimpleType("DWORD", rffi.UINT) - BOOL = rffi_platform.SimpleType("BOOL", rffi.LONG) - INT = rffi_platform.SimpleType("INT", rffi.INT) - LONG = rffi_platform.SimpleType("LONG", rffi.LONG) - PLONG = rffi_platform.SimpleType("PLONG", rffi.LONGP) - LPVOID = rffi_platform.SimpleType("LPVOID", rffi.INTP) - LPCVOID = rffi_platform.SimpleType("LPCVOID", rffi.VOIDP) - LPCTSTR = rffi_platform.SimpleType("LPCTSTR", rffi.CCHARP) - LPDWORD = rffi_platform.SimpleType("LPDWORD", rffi.INTP) - SIZE_T = rffi_platform.SimpleType("SIZE_T", rffi.SIZE_T) - - HRESULT = rffi_platform.SimpleType("HRESULT", rffi.LONG) - HLOCAL = rffi_platform.SimpleType("HLOCAL", rffi.VOIDP) - - DEFAULT_LANGUAGE = rffi_platform.ConstantInteger( - "MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT)") - - for name in """FORMAT_MESSAGE_ALLOCATE_BUFFER FORMAT_MESSAGE_FROM_SYSTEM - """.split(): - locals()[name] = rffi_platform.ConstantInteger(name) - - -for k, v in rffi_platform.configure(CConfig).items(): - globals()[k] = v - -def winexternal(name, args, result): - return rffi.llexternal(name, args, result, compilation_info=eci, calling_conv='win') - -if WIN32: - HANDLE = rffi.ULONG - LPHANDLE = rffi.CArrayPtr(HANDLE) - HMODULE = HANDLE - - GetLastError = winexternal('GetLastError', [], DWORD) - - LoadLibrary = winexternal('LoadLibraryA', [rffi.CCHARP], rffi.VOIDP) - GetProcAddress = winexternal('GetProcAddress', - [rffi.VOIDP, rffi.CCHARP], - rffi.VOIDP) - FreeLibrary = winexternal('FreeLibrary', [rffi.VOIDP], BOOL) - - LocalFree = winexternal('LocalFree', [HLOCAL], DWORD) - - FormatMessage = winexternal( - 'FormatMessageA', - [DWORD, rffi.VOIDP, DWORD, DWORD, rffi.CCHARP, DWORD, rffi.VOIDP], - DWORD) - - - # A bit like strerror... - def FormatError(code): - "Return a message corresponding to the given Windows error code." - buf = lltype.malloc(rffi.VOIDPP.TO, 1, flavor='raw') - - msglen = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM, - None, - code, - DEFAULT_LANGUAGE, - rffi.cast(rffi.VOIDP, buf), - 0, None) - - # FormatMessage always appends a \n. - msglen -= 1 - - result = ''.join([buf[0][i] for i in range(msglen)]) - LocalFree(buf[0]) - return result - - def FAILED(hr): - return rffi.cast(HRESULT, hr) < 0 - - _GetModuleFileName = winexternal('GetModuleFileNameA', - [HMODULE, rffi.CCHARP, DWORD], - DWORD) - - def GetModuleFileName(module): - size = 255 # MAX_PATH - buf = lltype.malloc(rffi.CCHARP.TO, size, flavor='raw') - res = _GetModuleFileName(module, buf, size) - if not res: - return '' - else: - return ''.join([buf[i] for i in range(res)]) +""" External functions accessing the win32 api. +Common types, functions from core win32 libraries, such as kernel32 +""" + +from pypy.rpython.tool import rffi_platform +from pypy.translator.tool.cbuild import ExternalCompilationInfo +from pypy.rpython.lltypesystem import lltype, rffi +import os + +# This module can be imported on any platform, +# but most symbols are not usable... +WIN32 = os.name == "nt" + +if WIN32: + eci = ExternalCompilationInfo( + includes = ['windows.h'], + libraries = ['kernel32'], + ) +else: + eci = ExternalCompilationInfo() + +class CConfig: + _compilation_info_ = eci + + if WIN32: + DWORD_PTR = rffi_platform.SimpleType("DWORD_PTR", rffi.LONG) + WORD = rffi_platform.SimpleType("WORD", rffi.UINT) + DWORD = rffi_platform.SimpleType("DWORD", rffi.UINT) + BOOL = rffi_platform.SimpleType("BOOL", rffi.LONG) + INT = rffi_platform.SimpleType("INT", rffi.INT) + LONG = rffi_platform.SimpleType("LONG", rffi.LONG) + PLONG = rffi_platform.SimpleType("PLONG", rffi.LONGP) + LPVOID = rffi_platform.SimpleType("LPVOID", rffi.INTP) + LPCVOID = rffi_platform.SimpleType("LPCVOID", rffi.VOIDP) + LPCTSTR = rffi_platform.SimpleType("LPCTSTR", rffi.CCHARP) + LPDWORD = rffi_platform.SimpleType("LPDWORD", rffi.INTP) + SIZE_T = rffi_platform.SimpleType("SIZE_T", rffi.SIZE_T) + + HRESULT = rffi_platform.SimpleType("HRESULT", rffi.LONG) + HLOCAL = rffi_platform.SimpleType("HLOCAL", rffi.VOIDP) + + DEFAULT_LANGUAGE = rffi_platform.ConstantInteger( + "MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT)") + + for name in """FORMAT_MESSAGE_ALLOCATE_BUFFER FORMAT_MESSAGE_FROM_SYSTEM + """.split(): + locals()[name] = rffi_platform.ConstantInteger(name) + + +for k, v in rffi_platform.configure(CConfig).items(): + globals()[k] = v + +def winexternal(name, args, result): + return rffi.llexternal(name, args, result, compilation_info=eci, calling_conv='win') + +if WIN32: + HANDLE = rffi.ULONG + LPHANDLE = rffi.CArrayPtr(HANDLE) + HMODULE = HANDLE + + GetLastError = winexternal('GetLastError', [], DWORD) + + LoadLibrary = winexternal('LoadLibraryA', [rffi.CCHARP], rffi.VOIDP) + GetProcAddress = winexternal('GetProcAddress', + [rffi.VOIDP, rffi.CCHARP], + rffi.VOIDP) + FreeLibrary = winexternal('FreeLibrary', [rffi.VOIDP], BOOL) + + LocalFree = winexternal('LocalFree', [HLOCAL], DWORD) + + FormatMessage = winexternal( + 'FormatMessageA', + [DWORD, rffi.VOIDP, DWORD, DWORD, rffi.CCHARP, DWORD, rffi.VOIDP], + DWORD) + + + # A bit like strerror... + def FormatError(code): + "Return a message corresponding to the given Windows error code." + buf = lltype.malloc(rffi.VOIDPP.TO, 1, flavor='raw') + + msglen = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM, + None, + code, + DEFAULT_LANGUAGE, + rffi.cast(rffi.VOIDP, buf), + 0, None) + + # FormatMessage always appends a \n. + msglen -= 1 + + result = ''.join([buf[0][i] for i in range(msglen)]) + LocalFree(buf[0]) + return result + + def FAILED(hr): + return rffi.cast(HRESULT, hr) < 0 + + _GetModuleFileName = winexternal('GetModuleFileNameA', + [HMODULE, rffi.CCHARP, DWORD], + DWORD) + + def GetModuleFileName(module): + size = 255 # MAX_PATH + buf = lltype.malloc(rffi.CCHARP.TO, size, flavor='raw') + res = _GetModuleFileName(module, buf, size) + if not res: + return '' + else: + return ''.join([buf[i] for i in range(res)]) Modified: pypy/dist/pypy/rpython/module/test/test_ll_os_environ.py ============================================================================== --- pypy/dist/pypy/rpython/module/test/test_ll_os_environ.py (original) +++ pypy/dist/pypy/rpython/module/test/test_ll_os_environ.py Thu May 22 19:15:25 2008 @@ -1,13 +1,13 @@ -from pypy.translator.c.test.test_genc import compile -import os - -def test_environ_items(): - - def foo(x): - if x: - return len(os.environ.items()) - else: - return 0 - f = compile(foo, [int], backendopt=False) - assert f(1) > 0 - +from pypy.translator.c.test.test_genc import compile +import os + +def test_environ_items(): + + def foo(x): + if x: + return len(os.environ.items()) + else: + return 0 + f = compile(foo, [int], backendopt=False) + assert f(1) > 0 + From arigo at codespeak.net Thu May 22 19:35:34 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 22 May 2008 19:35:34 +0200 (CEST) Subject: [pypy-svn] r55136 - in pypy/dist/pypy: tool translator/benchmark Message-ID: <20080522173534.E1044168477@codespeak.net> Author: arigo Date: Thu May 22 19:35:32 2008 New Revision: 55136 Modified: pypy/dist/pypy/tool/rundictbenchmarks.py pypy/dist/pypy/translator/benchmark/benchmarks.py Log: Some --text options left behind. Thanks amaury. Modified: pypy/dist/pypy/tool/rundictbenchmarks.py ============================================================================== --- pypy/dist/pypy/tool/rundictbenchmarks.py (original) +++ pypy/dist/pypy/tool/rundictbenchmarks.py Thu May 22 19:35:32 2008 @@ -16,7 +16,7 @@ ('richards', ['richards.py']), ('docutils', ['rst2html.py', '../../doc/coding-guide.txt', 'foo.html']), ('translate', ['translate.py', '--backendopt', '--no-compile', '--batch', - '--text', 'targetrpystonedalone.py']) + 'targetrpystonedalone.py']) ] EXE = sys.argv[1] Modified: pypy/dist/pypy/translator/benchmark/benchmarks.py ============================================================================== --- pypy/dist/pypy/translator/benchmark/benchmarks.py (original) +++ pypy/dist/pypy/translator/benchmark/benchmarks.py Thu May 22 19:35:32 2008 @@ -76,7 +76,7 @@ def run_translate(executable='/usr/local/bin/python'): translate = py.magic.autopath().dirpath().dirpath().join('goal').join('translate.py') target = py.magic.autopath().dirpath().dirpath().join('goal').join('targetrpystonedalone.py') - argstr = '%s %s --text --batch --backendopt --no-compile %s > /dev/null 2> /dev/null' + argstr = '%s %s --batch --backendopt --no-compile %s > /dev/null 2> /dev/null' T = time.time() status = os.system(argstr%(executable, translate, target)) r = time.time() - T From arigo at codespeak.net Thu May 22 19:37:58 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 22 May 2008 19:37:58 +0200 (CEST) Subject: [pypy-svn] r55137 - pypy/dist/pypy/translator/goal Message-ID: <20080522173758.25DB6168472@codespeak.net> Author: arigo Date: Thu May 22 19:37:58 2008 New Revision: 55137 Modified: pypy/dist/pypy/translator/goal/bench-cronjob.py Log: This change was made on tuatara a while ago already. Modified: pypy/dist/pypy/translator/goal/bench-cronjob.py ============================================================================== --- pypy/dist/pypy/translator/goal/bench-cronjob.py (original) +++ pypy/dist/pypy/translator/goal/bench-cronjob.py Thu May 22 19:37:58 2008 @@ -187,6 +187,7 @@ c--gc=marksweep--_faassen c--gc=semispace--_faassen c--gc=generation--_faassen + c--gc=hybrid--_faassen c--_objspace-std-withrope cli--_faassen jvm--_faassen From arigo at codespeak.net Thu May 22 20:35:56 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 22 May 2008 20:35:56 +0200 (CEST) Subject: [pypy-svn] r55140 - pypy/dist/pypy/lib Message-ID: <20080522183556.3EAD716804B@codespeak.net> Author: arigo Date: Thu May 22 20:35:55 2008 New Revision: 55140 Added: pypy/dist/pypy/lib/_pypy_irc_topic.py (contents, props changed) Modified: pypy/dist/pypy/lib/_pypy_interact.py Log: For fun only. Feel free to revert. Modified: pypy/dist/pypy/lib/_pypy_interact.py ============================================================================== --- pypy/dist/pypy/lib/_pypy_interact.py (original) +++ pypy/dist/pypy/lib/_pypy_interact.py Thu May 22 20:35:55 2008 @@ -5,6 +5,11 @@ def interactive_console(mainmodule=None): try: + import _pypy_irc_topic + print "``%s''" % (_pypy_irc_topic.some_topic(),) + except ImportError: + pass + try: from pyrepl.simple_interact import run_multiline_interactive_console except ImportError: run_simple_interactive_console(mainmodule) Added: pypy/dist/pypy/lib/_pypy_irc_topic.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/lib/_pypy_irc_topic.py Thu May 22 20:35:55 2008 @@ -0,0 +1,75 @@ +"""qvfgbcvna naq hgbcvna punvef +qlfgbcvna naq hgbcvna punvef +V'z fbeel, pbhyq lbh cyrnfr abg nterr jvgu gur png nf jryy? +V'z fbeel, pbhyq lbh cyrnfr abg nterr jvgu gur punve nf jryy? +jr cnffrq gur RH erivrj +cbfg RhebClguba fcevag fgnegf 12.IVV.2007, 10nz +RhebClguba raqrq +n Pyrna Ragrecevfrf cebqhpgvba +npnqrzl vf n pbzcyvpngrq ebyr tnzr +npnqrzvn vf n pbzcyvpngrq ebyr tnzr +jbexvat pbqr vf crn fbhc +abg lbhe snhyg, zber yvxr vg'f n zbivat gnetrg +guvf fragrapr vf snyfr +abguvat vf gehr +Yncfnat Fbhpubat +Oenpunzhgnaqn +fbeel, V'yy grnpu gur pnpghf ubj gb fjvz yngre +Jul fb znal znal znal znal znal ivbyvaf? +Jul fb znal znal znal znal znal bowrpgf? +"eha njnl naq yvir ba n snez" nccebnpu gb fbsgjner qrirybczrag +"va snpg, lbh zvtug xabj zber nobhg gur genafyngvba gbbypunva nsgre znfgrevat eclguba guna fbzr angvir fcrnxre xabjf nobhg uvf zbgure gbathr" - kbeNkNk +"jurer qvq nyy gur ivbyvaf tb?" +- ClCl fgnghf oybt: uggc://zberclcl.oybtfcbg.pbz/ +uggc://kxpq.pbz/353/ +pnfhnyvgl ivbyngvbaf naq sylvat +wrgmg abpu fpubxbynqvtre +R09 2X @PNN:85? +vs lbh'er gelvat gb oybj hc fghss, jub pnerf? +vs fghss oybjf hc, lbh pner +2008 jvyy or gur lrne bs clcl ba gur qrfxgbc +2008 jvyy or gur lrne bs gur qrfxgbc ba #clcl +2008 jvyy or gur lrne bs gur qrfxgbc ba #clcl, Wnahnel jvyy or gur zbagu bs gur nyc gbcf +lrf, ohg jung'g gur frafr bs 0 < "qhena qhena" +eclguba: flagnk naq frznagvpf bs clguba, fcrrq bs p, erfgevpgvbaf bs wnin naq pbzcvyre reebe zrffntrf nf crargenoyr nf ZHZCF +pglcrf unf n fcva bs 1/3 +' ' vf n fcnpr gbb +2009 jvyy or gur lrne bs WVG ba gur qrfxgbc +N ynathntr vf n qvnyrpg jvgu na nezl naq anil +gbcvpf ner sbe gur srroyr zvaqrq +2009 vf gur lrne bs ersyrpgvba ba gur qrfxgbc +gur tybor vf bhe cbal, gur pbfzbf bhe erny ubefr +jub nz V naq vs lrf, ubj znal? +cebtenzzvat va orq vf n cresrpgyl svar npgvivgl +zbber'f ynj vf n qeht jvgu gur jbefg pbzr qbja +EClguba: jr hfr vg fb lbh qba'g unir gb +Zbber'f ynj vf n qeht jvgu gur jbefg pbzr qbja. EClguba: haqrpvqrq. +guvatf jvyy or avpr naq fghss +qba'g cbfg yvaxf gb cngragf urer +Abg lbhe hfhny nanylfrf. +Gur Neg bs gur Punaary +Clguba 300 +V fhccbfr ZO bs UGZY cre frpbaq vf abg gur hfhny fcrrq zrnfher crbcyr jbhyq rkcrpg sbe n wvg +gur fha arire frgf ba gur ClCl rzcver +ghegyrf ner snfgre guna lbh guvax +cebtenzzvat vf na nrfgrguvp raqrnibhe +P vf tbbq sbe fbzrguvat, whfg abg sbe jevgvat fbsgjner +trezna vf tbbq sbe fbzrguvat, whfg abg sbe jevgvat fbsgjner +trezna vf tbbq sbe artngvbaf, whfg abg sbe jevgvat fbsgjner +# nffreg qvq abg penfu +lbh fubhyq fgneg n cresrpg fbsgjner zbirzrag +lbh fubhyq fgneg n cresrpg punaary gbcvp zbirzrag +guvf vf n cresrpg punaary gbcvp +guvf vf n frys-ersreragvny punaary gbcvp +crrcubcr bcgvzvmngvbaf ner jung n Fhssvpvragyl Fzneg Pbzcvyre hfrf +"crrcubcr" bcgvzvmngvbaf ner jung na bcgvzvfgvp Pbzcvyre hfrf +pubbfr lbhe unpx +gur 'fhcre' xrljbeq vf abg gung uhttnoyr +wlguba cngpurf ner abg rabhtu sbe clcl +- qb lbh xabj oreyva? - nyy bs vg? - jryy, whfg oreyva +""" + +def some_topic(): + import time + lines = __doc__.splitlines() + return lines[int(time.time()) % len(lines)].decode('rot13') From tverwaes at codespeak.net Thu May 22 22:21:11 2008 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Thu, 22 May 2008 22:21:11 +0200 (CEST) Subject: [pypy-svn] r55142 - in pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk: . test Message-ID: <20080522202111.EF9881684E1@codespeak.net> Author: tverwaes Date: Thu May 22 22:21:09 2008 New Revision: 55142 Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_model.py Log: fixing at(put)0 for W_WordsObject Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py Thu May 22 22:21:09 2008 @@ -403,11 +403,11 @@ def at0(self, index0): from pypy.lang.smalltalk import utility - return utility.wrap_int(self.getword(index0)) + return self.getword(index0) def atput0(self, index0, w_value): from pypy.lang.smalltalk import utility - self.setword(index0, utility.unwrap_int(w_value)) + self.setword(index0, w_value) def getword(self, n): return self.words[n] Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_model.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_model.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_model.py Thu May 22 22:21:09 2008 @@ -196,3 +196,12 @@ assert res assert w_clsa.as_class_get_shadow() is s_clsb assert w_clsb.as_class_get_shadow() is s_clsa + +def test_wordsobject_at0_atput0(): + w_words = model.W_WordsObject(None, 3) + w_words.atput0(0, 'a') + w_words.atput0(1, 'b') + w_words.atput0(2, 'c') + assert w_words.at0(0) == 'a' + assert w_words.at0(1) == 'b' + assert w_words.at0(2) == 'c' From cami at codespeak.net Fri May 23 10:03:07 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Fri, 23 May 2008 10:03:07 +0200 (CEST) Subject: [pypy-svn] r55144 - in pypy/dist/pypy/lang/gameboy: . test Message-ID: <20080523080307.A1494168514@codespeak.net> Author: cami Date: Fri May 23 10:03:02 2008 New Revision: 55144 Modified: pypy/dist/pypy/lang/gameboy/cartridge.py pypy/dist/pypy/lang/gameboy/cpu.py pypy/dist/pypy/lang/gameboy/gameboy.py pypy/dist/pypy/lang/gameboy/gameboyImplementation.py pypy/dist/pypy/lang/gameboy/test/test_cartridge.py pypy/dist/pypy/lang/gameboy/test/test_rom.py pypy/dist/pypy/lang/gameboy/timer.py Log: visual test roms 9 and 8 are working now added step by step rom tests fixed relative jump offset bug in cpu escaped some useless print statements in timer changed DefaultMBC such that it supports reading and writing now adapted test_rom and test_cartridge Modified: pypy/dist/pypy/lang/gameboy/cartridge.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/cartridge.py (original) +++ pypy/dist/pypy/lang/gameboy/cartridge.py Fri May 23 10:03:02 2008 @@ -65,11 +65,12 @@ def write(self, address, data): self.mbc.write(address, data) - def load(self, cartridge): - assert isinstance(cartridge, Cartridge) + def load(self, cartridge, verify=True): + assert isinstance(cartridge, CartridgeFile) self.cartridge = cartridge self.rom = self.cartridge.read() - self.check_rom() + if verify: + self.check_rom() self.create_ram() self.load_battery() self.mbc = self.create_bank_controller(self.get_memory_bank_type(), \ @@ -149,14 +150,13 @@ return (checksum == self.get_header_checksum()) def create_bank_controller(self, type, rom, ram, clock_driver): - print "create_bank_controller: ", type return MEMORY_BANK_MAPPING[type](rom, ram, clock_driver) # ------------------------------------------------------------------------------ -class Cartridge(object): +class CartridgeFile(object): """ File mapping. Holds the file contents """ @@ -305,6 +305,9 @@ max_rom_bank_size=0xFFFFFF, min_ram_bank_size=0, max_ram_bank_size=0xFFFFFF) + + def write(self, address, data): + self.ram[address] = data #------------------------------------------------------------------------------- @@ -348,7 +351,6 @@ def write_ram_enable(self, address, data): if self.ram_size > 0: self.ram_enable = ((data & 0x0A) == 0x0A) - print "write_ram_enable: ", hex(self.ram_enable) def write_rom_bank_1(self, address, data): if (data & 0x1F) == 0: Modified: pypy/dist/pypy/lang/gameboy/cpu.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/cpu.py (original) +++ pypy/dist/pypy/lang/gameboy/cpu.py Fri May 23 10:03:02 2008 @@ -29,11 +29,18 @@ return self.value def add(self, value, use_cycles=True): + value = self.process_2_complement(value) self.set(self.get(use_cycles)+value, use_cycles) def sub(self, value, use_cycles=True): self.set(self.get(use_cycles)-value, use_cycles) + def process_2_complement(self, value): + # check if the left most bit is set + if (value >> 7) == 1: + return -(~value) & 0xFF-1 + else : + return value #------------------------------------------------------------------------------ class DoubleRegister(iRegister): @@ -48,6 +55,7 @@ self.reset_value = reset_value def set(self, value, use_cycles=True): + value = value & 0xFFFF self.set_hi(value >> 8, use_cycles) self.set_lo(value & 0xFF, use_cycles) if use_cycles: @@ -85,10 +93,20 @@ if use_cycles: self.cpu.cycles -= 1 - def add(self, n=2, use_cycles=True): - self.set(self.get(use_cycles) + n, use_cycles=use_cycles) + def add(self, value, use_cycles=True): + value = self.process_2_complement(value) + self.set(self.get(use_cycles) + value, use_cycles=use_cycles) if use_cycles: self.cpu.cycles -= 2 + + def process_2_complement(self, value): + if value > 0xFF: + return value + # check if the left most bit is set + elif (value >> 7) == 1: + return -((~value) & 0xFF)-1 + else : + return value # ------------------------------------------------------------------------------ @@ -166,23 +184,18 @@ self.reset() if isinstance(a, (Register)): a = a.get() - print " "*8, a, "z_flag_compare", self.z_flag self.z_flag = ((a & 0xFF) == 0) - print self.z_flag def c_flag_add(self, s, compare_and=0x01, reset=False): if reset: self.reset() - if (s & compare_and) != 0: - self.c_flag = True + self.c_flag = ((s & compare_and) != 0) def h_flag_compare(self, a, b): - if (a & 0x0F) < (b & 0x0F): - self.h_flag = True + self.h_flag = ((a & 0x0F) < (b & 0x0F)) - def c_flag_compare(self, a, b): - if a < b: - self.c_flag = True + def c_flag_compare(self, a, b): + self.c_flag = (a < b) # # ------------------------------------------------------------------------------ @@ -236,6 +249,8 @@ self.halted = False self.cycles = 0 self.instruction_counter = 0 + self.last_op_code = -1 + self.last_fetch_execute_op_code = -1 def reset_registers(self): self.a.reset() @@ -338,11 +353,15 @@ # --------------------------------------------------------------- def emulate(self, ticks): - ticks = int(ticks) self.cycles += ticks self.handle_pending_interrupt() while self.cycles > 0: self.execute(self.fetch()) + + def emulate_step(self): + self.handle_pending_interrupt() + self.execute(self.fetch()) + def handle_pending_interrupt(self): # Interrupts @@ -366,18 +385,19 @@ def fetch_execute(self): # Execution opCode = self.fetch() - print " fetch exe:", hex(opCode), " " + #print " fetch exe:", hex(opCode), " " #, FETCH_EXECUTE_OP_CODES[opCode].__name__ + self.last_fetch_execute_op_code = opCode FETCH_EXECUTE_OP_CODES[opCode](self) def execute(self, opCode): self.instruction_counter += 1 - print self.instruction_counter, "-"*60 - print "exe: ", hex(opCode), " " - #, OP_CODES[opCode].__name__ - print " pc:", hex(self.pc.get()), "sp:", hex(self.sp.get()) - self.print_registers() + #print self.instruction_counter, "-"*60 + #print "exe: ", hex(opCode), " ", OP_CODES[opCode].__name__ + #print " pc:", hex(self.pc.get()), "sp:", hex(self.sp.get()) + #self.print_registers() + self.last_op_code = opCode OP_CODES[opCode](self) def print_registers(self): @@ -402,7 +422,7 @@ return self.memory.read(address) def write(self, address, data): - print " write: ", "a:", hex(address), "v:", hex(data) + # print " write: ", "a:", hex(address), "v:", hex(data) # 2 cycles self.memory.write(address, data) self.cycles -= 2 @@ -415,7 +435,7 @@ else: data = self.memory.read(self.pc.get(use_cycles)) self.pc.inc(use_cycles) # 2 cycles - print " fetch: ", data + # print " fetch: ", data return data def fetch_double_address(self): @@ -565,25 +585,32 @@ self.f.z_flag_compare(self.a.get(), reset=True) def inc_double_register(self, doubleRegister): - doubleRegister.inc() + self.inc(doubleRegister.get, doubleRegister.set) def dec_double_register(self, doubleRegister): - doubleRegister.dec() + self.dec(doubleRegister.get, doubleRegister.set) def inc(self, getCaller, setCaller): - # 1 cycle - data = (getCaller.get() + 1) & 0xFF - self.dec_inc_flag_finish(data, setCaller, 0x00) + if getCaller.register == self.a: + self.add_a(NumberCallWrapper(1)) + else: + # 1 cycle + data = (getCaller.get() + 1) & 0xFF + self.dec_inc_flag_finish(data, setCaller, 0x00) def dec(self, getCaller, setCaller): - # 1 cycle - data = (getCaller.get() - 1) & 0xFF - self.dec_inc_flag_finish(data, setCaller, 0x0F) - self.f.n_flag = True + if setCaller.register == self.a: + self.subtract_a(NumberCallWrapper(1)) + else: + # 1 cycle + data = (getCaller.get() - 1) & 0xFF + self.dec_inc_flag_finish(data, setCaller, 0x0F) + self.f.n_flag = True def dec_inc_flag_finish(self, data, setCaller, compare): self.f.partial_reset(keep_c=True) self.f.z_flag_compare(data) + self.f.c_flag_compare(data, self.a.get()) if (data & 0x0F) == compare: self.f.h_flag = True setCaller.set(data) # 1 cycle @@ -849,6 +876,7 @@ def relative_unconditional_jump(self): # JR +nn, 3 cycles + #pc = pc & 0xFF00 + ((pc & 0x00FF) + add) & 0xFF self.pc.add(self.fetch()) # 3 + 1 cycles self.cycles += 1 @@ -930,6 +958,18 @@ def set(self, value, use_cycles=True): raise Exception("called CalLWrapper.set") pass + +class NumberCallWrapper(CallWrapper): + + def __init__(self, number): + self.number = number + + def get(self, use_cycles=True): + return self.number + + def set(self, value, use_cycles=True): + raise Exception("called CalLWrapper.set") + pass class RegisterCallWrapper(CallWrapper): def __init__(self, register): Modified: pypy/dist/pypy/lang/gameboy/gameboy.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/gameboy.py (original) +++ pypy/dist/pypy/lang/gameboy/gameboy.py Fri May 23 10:03:02 2008 @@ -44,12 +44,12 @@ def get_cartridge_manager(self): return self.cartridge_manager - def load_cartridge(self, cartridge): - self.cartridge_manager.load(cartridge) + def load_cartridge(self, cartridge, verify=True): + self.cartridge_manager.load(cartridge, verify) self.cpu.set_rom(self.cartridge_manager.get_rom()) - def load_cartridge_file(self, path): - self.load_cartridge(Cartridge(path)) + def load_cartridge_file(self, path, verify=True): + self.load_cartridge(CartridgeFile(path), verify) def get_frame_skip(self): return self.video.get_frame_skip() @@ -101,13 +101,23 @@ ticks -= count return 0 + def emulate_step(self): + self.cpu.emulate_step() + self.serial.emulate(1) + self.timer.emulate(1) + self.video.emulate(1) + self.sound.emulate(1) + self.joypad.emulate(1) + def print_cycles(self): - for element in [(" video:", self.video), - ("serial:", self.serial), - (" timer:", self.timer), - (" sound:", self.sound), - ("joypad:", self.joypad)]: - print " ", element[0], element[1].get_cycles() + return + #for element in [(" video:", self.video), + # ("serial:", self.serial), + # (" timer:", self.timer), + # (" sound:", self.sound), + # ("joypad:", self.joypad)]: + # #print " ", element[0], element[1].get_cycles() + # pass def write(self, address, data): receiver = self.get_receiver(address) @@ -122,7 +132,8 @@ return receiver.read(address) def print_receiver_msg(self, address, name): - print " recei: ", hex(address), name + #print " recei: ", hex(address), name + pass def get_receiver(self, address): if 0x0000 <= address <= 0x7FFF: Modified: pypy/dist/pypy/lang/gameboy/gameboyImplementation.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/gameboyImplementation.py (original) +++ pypy/dist/pypy/lang/gameboy/gameboyImplementation.py Fri May 23 10:03:02 2008 @@ -72,19 +72,19 @@ self.screen = RSDL.SetVideoMode(self.width, self.height, 32, 0) def update_display(self): - RSDL.LockSurface(self.screen) + print " update_display" + #RSDL.LockSurface(self.screen) self.draw_pixels() - RSDL.UnlockSurface(self.screen) - RSDL.Flip(self.screen) - pass + #RSDL.UnlockSurface(self.screen) + #RSDL.Flip(self.screen) def draw_pixels(self): print "-"*60 - for x in range(self.width): + for y in range(self.height): str = "" - for y in range(self.height): + for x in range(self.width): str += self.pixel_map(x, y) - #RSDL_helper.set_pixel(self.screen, x, y, self.get_pixel_color(x, y)) + RSDL_helper.set_pixel(self.screen, x, y, self.get_pixel_color(x, y)) print str; print "-"*60 @@ -94,8 +94,8 @@ b = px & 0xFF g = (px>>8) & 0xFF r = (px>>16) & 0xFF - brightness = 4*r+b+g / 0xFFFFFF - return [".", "+", "O", "#"][brightness] + brightness = 4 * (r+b+g) / (0xFF*3) + return [".", "+", "O", "#", ""][brightness] def get_pixel_color(self, x, y): return self.pixels[x+self.width*y] @@ -201,16 +201,16 @@ import pdb def entry_point(argv=None): - print "startin gameboy emulation" - gameboy = GameBoyImplementation() - if argv is not None and len(argv) > 1: - filename = argv[1] + if argv is not None and len(argv) > 0: + filename = argv[0] else: - #filename = gameboy.load() - filename = ROM_PATH+"/rom9/rom9.gb" + pos = str(8) + filename = ROM_PATH+"/rom"+pos+"/rom"+pos+".gb" print "loading rom: ", str(filename) - gameboy.load_cartridge_file(str(filename)) - pdb.runcall(gameboy.mainLoop) + gameBoy = GameBoyImplementation() + gameBoy.load_cartridge_file(str(filename)) + gameBoy.mainLoop() + #pdb.runcall(gameBoy.mainLoop) return 0 @@ -223,5 +223,3 @@ entry_point() - - \ No newline at end of file Modified: pypy/dist/pypy/lang/gameboy/test/test_cartridge.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/test/test_cartridge.py (original) +++ pypy/dist/pypy/lang/gameboy/test/test_cartridge.py Fri May 23 10:03:02 2008 @@ -19,7 +19,7 @@ pass def get_cartridge(): - ctrg = Cartridge() + ctrg = CartridgeFile() return ctrg class File(object): Modified: pypy/dist/pypy/lang/gameboy/test/test_rom.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/test/test_rom.py (original) +++ pypy/dist/pypy/lang/gameboy/test/test_rom.py Fri May 23 10:03:02 2008 @@ -11,71 +11,240 @@ # ------------------------------------------------------------------------------ +def emulate_step_op_codes_test(gameboy, op_codes): + count = 0 + for op_code in op_codes: + gameboy.emulate_step() + assert gameboy.cpu.last_op_code == op_code, \ + "Excpected: %s got %s, turn: %i" % \ + ( hex(op_code), hex(gameboy.cpu.last_op_code), count) + count += 1 -def test_rom1(): - gameBoy = GameBoy() +# ------------------------------------------------------------------------------ + +def test_rom1_load(): + gameboy = GameBoy() try: - gameBoy.load_cartridge_file(ROM_PATH+"/rom1/rom1.raw") + gameboy.load_cartridge_file(ROM_PATH+"/rom1/rom1.raw") py.test.fail() except: pass +def test_rom1_step(): + py.test.skip() + gameboy = GameBoy() + gameboy.load_cartridge_file(ROM_PATH+"/rom1/rom1.raw", verify=False) + emulate_step_op_codes_test(gameboy, []) + +# ------------------------------------------------------------------------------ -def test_rom2(): - gameBoy = GameBoy() +def test_rom2_load(): + gameboy = GameBoy() try: - gameBoy.load_cartridge_file(ROM_PATH+"/rom2/rom2.raw") + gameboy.load_cartridge_file(ROM_PATH+"/rom2/rom2.raw") py.test.fail() except: pass - -def test_rom3(): +# ------------------------------------------------------------------------------ + +def test_rom3_load(): """ some NOP and an endless loop at the end '""" - gameBoy = GameBoy() - gameBoy.load_cartridge_file(ROM_PATH+"/rom3/rom3.gb") - gameBoy.emulate(EMULATION_CYCLES) - + gameboy = GameBoy() + gameboy.load_cartridge_file(ROM_PATH+"/rom3/rom3.gb") + gameboy.emulate(EMULATION_CYCLES) -def test_rom4(): - gameBoy = GameBoy() - gameBoy.load_cartridge_file(ROM_PATH+"/rom4/rom4.gb") - gameBoy.emulate(EMULATION_CYCLES) + +def test_rom3_step(): + py.test.skip() + gameboy = GameBoy() + gameboy.load_cartridge_file(ROM_PATH+"/rom3/rom3.gb") + # jp nop + emulate_step_op_codes_test(gameboy, [0xC3]) + emulate_step_op_codes_test(gameboy, [0]*12) + emulate_step_op_codes_test(gameboy, [0xC3]*100) - assert gameBoy.cpu.ime == False - assert gameBoy.cpu.halted == True - assert gameBoy.cpu.a.get() != 0xFF +# ------------------------------------------------------------------------------ + +def test_rom4_load(): + gameboy = GameBoy() + gameboy.load_cartridge_file(ROM_PATH+"/rom4/rom4.gb") + gameboy.emulate(EMULATION_CYCLES) + + assert gameboy.cpu.ime == False + assert gameboy.cpu.halted == True + assert gameboy.cpu.a.get() != 0xFF + +def test_rom4_step(): + gameboy = GameBoy() + gameboy.load_cartridge_file(ROM_PATH+"/rom4/rom4.gb") + emulate_step_op_codes_test(gameboy, [0, 0xC3, 0xF3, 0x21]) + assert gameboy.cpu.hl.get() == 0xFF40 + emulate_step_op_codes_test(gameboy, [0xCB, 0x76, 0x76, 0x3E]) + +# ------------------------------------------------------------------------------ -def test_rom5(): - gameBoy = GameBoy() - gameBoy.load_cartridge_file(ROM_PATH+"/rom5/rom5.gb") - gameBoy.emulate(EMULATION_CYCLES) +def test_rom5_load(): + gameboy = GameBoy() + gameboy.load_cartridge_file(ROM_PATH+"/rom5/rom5.gb") + gameboy.emulate(EMULATION_CYCLES) # stop test - assert gameBoy.cpu.a.get() != 0xFF + assert gameboy.cpu.a.get() != 0xFF + +def test_rom5_step(): + gameboy = GameBoy() + gameboy.load_cartridge_file(ROM_PATH+"/rom5/rom5.gb") + + emulate_step_op_codes_test(gameboy, [0, 0xC3, 0xF3, 0xAF, 0x3D, 0xC2]) + assert gameboy.cpu.pc.get() == 0x0152 + assert gameboy.cpu.a.get() == 0xFF + emulate_step_op_codes_test(gameboy, [0x3D, 0xC2]*0xFF) + assert gameboy.cpu.a.get() == 0 + + emulate_step_op_codes_test(gameboy, [0xDD, 0xAF, 0xC6]) + pc = gameboy.cpu.pc.get() + assert gameboy.cpu.a.get() == 1 + assert gameboy.cpu.f.c_flag == False + emulate_step_op_codes_test(gameboy, [0x30]) + assert gameboy.cpu.pc.get() == pc-2 + emulate_step_op_codes_test(gameboy, [0xC6, 0x30]*255) + assert gameboy.cpu.a.get() == 0 + assert gameboy.cpu.f.c_flag == True + + emulate_step_op_codes_test(gameboy, [0xDD, 0xAF]) + assert gameboy.cpu.a.get() == 0 + assert gameboy.cpu.f.c_flag == False + pc = gameboy.cpu.pc.get() + emulate_step_op_codes_test(gameboy, [0x3C, 0xD2]) + assert gameboy.cpu.f.c_flag == False + assert gameboy.cpu.a.get() == 1 + assert gameboy.cpu.pc.get() == pc + emulate_step_op_codes_test(gameboy, [0x3C, 0xD2]*255) + assert gameboy.cpu.a.get() == 0 + assert gameboy.cpu.f.c_flag == True -def test_rom6(): - gameBoy = GameBoy() - gameBoy.load_cartridge_file(ROM_PATH+"/rom6/rom6.gb") - gameBoy.emulate(EMULATION_CYCLES) + emulate_step_op_codes_test(gameboy, [0xDD, 0x76, 0x76]) +# ------------------------------------------------------------------------------ -def test_rom7(): +def test_rom6_load(): + gameboy = GameBoy() + gameboy.load_cartridge_file(ROM_PATH+"/rom6/rom6.gb") + gameboy.emulate(EMULATION_CYCLES) + +def test_rom6_step(): + gameboy = GameBoy() + gameboy.load_cartridge_file(ROM_PATH+"/rom6/rom6.gb") + cpu = gameboy.cpu + + emulate_step_op_codes_test(gameboy, [0, 0xC3, 0xF3, 0x21, 0xF9]) + assert cpu.hl.get() == 0xC200 + assert cpu.sp.get() == cpu.hl.get() + + emulate_step_op_codes_test(gameboy, [0x3E, 0xEA]) + assert cpu.a.get() == 0x01 + #assert cpu.read(0x6000) == cpu.a.get() + + emulate_step_op_codes_test(gameboy, [0x3E, 0xEA]) + assert cpu.a.get() == 0x01 + #assert cpu.read(0x2000) == cpu.a.get() + + emulate_step_op_codes_test(gameboy, [0x3E, 0xEA]) + assert cpu.a.get() == 0x00 + #assert cpu.read(0x4000) == cpu.a.get() + + emulate_step_op_codes_test(gameboy, [0x3E, 0xEA]) + assert cpu.a.get() == 0x0A + #assert cpu.read(0x0000) == cpu.a.get() + + emulate_step_op_codes_test(gameboy, [0x21, 0x01, 0x3E]) + assert cpu.hl.get() == 0xA000 + assert cpu.bc.get() == 0x0020 + assert cpu.a.get() == 0xFF + + def call_mem_set(): + pc_return = cpu.pc.get() + emulate_step_op_codes_test(gameboy, [0xCD]) + assert cpu.pc.get() == 0x0198 + + pc, b, c = cpu.pc.get(), cpu.b.get(), cpu.c.get() + emulate_step_op_codes_test(gameboy, [0x04, 0x0C, 0x18]) + assert cpu.b.get() == b+1 + assert cpu.c.get() == c+1 + assert cpu.pc.get() == pc+5 + + c = cpu.c.get() + emulate_step_op_codes_test(gameboy, [0x0D, 0x20]) + assert cpu.c.get() == c-1 + + while not cpu.f.z_flag: + hl = cpu.hl.get() + emulate_step_op_codes_test(gameboy, [0x22]) + assert cpu.hl.get() == hl+1 + #assert cpu.read(cpu.hl.get()) == cpu.a.get() + + emulate_step_op_codes_test(gameboy, [0x0D, 0x20]) + + b = cpu.b.get() + emulate_step_op_codes_test(gameboy, [0x05, 0x20]) + assert cpu.b.get() == b-1 + + emulate_step_op_codes_test(gameboy, [0xC9]) + assert cpu.pc.get() == pc_return+3 + + call_mem_set() + + emulate_step_op_codes_test(gameboy, [0x3E, 0xEA, 0x21, 0x01]) + assert cpu.a.get() == 0x01 + #assert cpu.read(0x4000) == cpu.a.get() + assert cpu.hl.get() == 0xA000 + assert cpu.bc.get() == 0x0020 + emulate_step_op_codes_test(gameboy, [0x3E]) + assert cpu.a.get() == 0x22 + + call_mem_set() + + + emulate_step_op_codes_test(gameboy, [0x3E, 0xEA]) + assert cpu.a.get() == 0x00 + + emulate_step_op_codes_test(gameboy, [0x3E, 0x21, 0xBE]) + assert cpu.a.get() == 0xFF + assert cpu.hl.get() == 0xA000 + assert cpu.read(cpu.hl.get()) == cpu.a.get() + + emulate_step_op_codes_test(gameboy, [0x20, 0xAF, 0x76, 0x76, 0xdd]) + assert cpu.a.get() == 0 + + + +# ------------------------------------------------------------------------------ + +def test_rom7_load(): + py.test.skip("Current Default ROM Implemenation doesnt allow write") + gameboy = GameBoy() + gameboy.load_cartridge_file(ROM_PATH+"/rom7/rom7.gb") + gameboy.emulate(EMULATION_CYCLES) + + +def test_rom7_step(): py.test.skip("Current Default ROM Implemenation doesnt allow write") - gameBoy = GameBoy() - gameBoy.load_cartridge_file(ROM_PATH+"/rom7/rom7.gb") - gameBoy.emulate(EMULATION_CYCLES) + +# ------------------------------------------------------------------------------ + +def test_rom8_load(): + gameboy = GameBoy() + gameboy.load_cartridge_file(ROM_PATH+"/rom8/rom8.gb") + gameboy.emulate(EMULATION_CYCLES) -def test_rom8(): - gameBoy = GameBoy() - gameBoy.load_cartridge_file(ROM_PATH+"/rom8/rom8.gb") - gameBoy.emulate(EMULATION_CYCLES) +# ------------------------------------------------------------------------------ def test_rom9(): - gameBoy = GameBoy() - gameBoy.load_cartridge_file(ROM_PATH+"/rom9/rom9.gb") - gameBoy.emulate(EMULATION_CYCLES) + gameboy = GameBoy() + gameboy.load_cartridge_file(ROM_PATH+"/rom9/rom9.gb") + gameboy.emulate(EMULATION_CYCLES) Modified: pypy/dist/pypy/lang/gameboy/timer.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/timer.py (original) +++ pypy/dist/pypy/lang/gameboy/timer.py Fri May 23 10:03:02 2008 @@ -26,7 +26,6 @@ self.tac = 0 self.timer_cycles = constants.TIMER_CLOCK[0] self.timer_clock = constants.TIMER_CLOCK[0] - print constants.TIMER_CLOCK def write(self, address, data): address = int(address) @@ -94,7 +93,6 @@ while self.divider_cycles <= 0: self.div = (self.div + 1) & 0xFF; self.divider_cycles += constants.DIV_CLOCK; - print self.divider_cycles def emulate_timer(self, ticks): if (self.tac & 0x04) == 0: From cami at codespeak.net Fri May 23 10:32:47 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Fri, 23 May 2008 10:32:47 +0200 (CEST) Subject: [pypy-svn] r55145 - pypy/dist/pypy/translator/goal Message-ID: <20080523083247.00975168444@codespeak.net> Author: cami Date: Fri May 23 10:32:47 2008 New Revision: 55145 Modified: pypy/dist/pypy/translator/goal/targetsimplevideo.py Log: increased the wnidow size to check the speed in c, for use on top o cpython the screen size needs to be reduced Modified: pypy/dist/pypy/translator/goal/targetsimplevideo.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetsimplevideo.py (original) +++ pypy/dist/pypy/translator/goal/targetsimplevideo.py Fri May 23 10:32:47 2008 @@ -2,8 +2,8 @@ from pypy.rpython.lltypesystem import rffi, lltype import py -WIDTH = 20 -HEIGHT = 20 +WIDTH = 1000 +HEIGHT = 1000 def entry_point(argv=None): RSDL.Init(RSDL.INIT_VIDEO) >= 0 From cfbolz at codespeak.net Fri May 23 12:18:03 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 23 May 2008 12:18:03 +0200 (CEST) Subject: [pypy-svn] r55146 - pypy/extradoc/paper Message-ID: <20080523101803.94B85168514@codespeak.net> Author: cfbolz Date: Fri May 23 12:18:01 2008 New Revision: 55146 Added: pypy/extradoc/paper/spy-s3.pdf (contents, props changed) Log: check in spy s3 paper as it was in the preproceedings Added: pypy/extradoc/paper/spy-s3.pdf ============================================================================== Binary file. No diff available. From afa at codespeak.net Fri May 23 15:45:26 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 23 May 2008 15:45:26 +0200 (CEST) Subject: [pypy-svn] r55148 - in pypy/dist/pypy/translator/c: . test Message-ID: <20080523134526.D3E5616800C@codespeak.net> Author: afa Date: Fri May 23 15:45:25 2008 New Revision: 55148 Modified: pypy/dist/pypy/translator/c/node.py pypy/dist/pypy/translator/c/test/test_lltyped.py Log: Avoid the creation of an empty structure when Arrays of Void are used. This happens in _rawffi, and shows up when inlining is disabled. (I disabled inlining because translation then only needs 410Mb of RAM... and fits on my home PC when not too many modules are added) Modified: pypy/dist/pypy/translator/c/node.py ============================================================================== --- pypy/dist/pypy/translator/c/node.py (original) +++ pypy/dist/pypy/translator/c/node.py Fri May 23 15:45:25 2008 @@ -261,7 +261,9 @@ yield '\tlong length;' line = '%s;' % cdecl(self.itemtypename, 'items[%d]'% self.varlength) if self.ARRAY.OF is Void: # strange - line = '/* %s */' % line + line = '/* array of void */' + if self.ARRAY._hints.get('nolength', False): + line = 'char _dummy; ' + line yield '\t' + line yield '};' Modified: pypy/dist/pypy/translator/c/test/test_lltyped.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_lltyped.py (original) +++ pypy/dist/pypy/translator/c/test/test_lltyped.py Fri May 23 15:45:25 2008 @@ -650,3 +650,10 @@ fn = self.getcompiled(llf) fn() + def test_cast_to_void_array(self): + from pypy.rpython.lltypesystem import rffi + def llf(): + TYPE = Ptr(rffi.CArray(Void)) + y = rffi.cast(TYPE, 0) + fn = self.getcompiled(llf) + fn() From cfbolz at codespeak.net Fri May 23 16:22:40 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 23 May 2008 16:22:40 +0200 (CEST) Subject: [pypy-svn] r55149 - in pypy/branch/smalltalk-shadow-changes/pypy/translator/backendopt: . test Message-ID: <20080523142240.5C1A9168430@codespeak.net> Author: cfbolz Date: Fri May 23 16:22:38 2008 New Revision: 55149 Modified: pypy/branch/smalltalk-shadow-changes/pypy/translator/backendopt/malloc.py pypy/branch/smalltalk-shadow-changes/pypy/translator/backendopt/test/test_malloc.py Log: a tentative fix for the malloc removal problems Modified: pypy/branch/smalltalk-shadow-changes/pypy/translator/backendopt/malloc.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/translator/backendopt/malloc.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/translator/backendopt/malloc.py Fri May 23 16:22:38 2008 @@ -63,11 +63,10 @@ def inline_type(self, TYPE): raise NotImplementedError - def flowin(self, block, count, var, newvarsmap): + def flowin(self, block, count, vars, newvarsmap): # in this 'block', follow where the 'var' goes to and replace # it by a flattened-out family of variables. This family is given # by newvarsmap, whose keys are the 'flatnames'. - vars = {var: True} self.last_removed_access = None def list_newvars(): @@ -82,7 +81,6 @@ self.flowin_op(op, vars, newvarsmap) elif op.result in vars: assert op.opname == self.MALLOC_OP - assert vars == {var: True} progress = True # drop the "malloc" operation newvarsmap = self.flatconstants.copy() # zero initial values @@ -106,10 +104,13 @@ assert block.exitswitch not in vars for link in block.exits: + appended = False newargs = [] for arg in link.args: if arg in vars: - newargs += list_newvars() + if not appended: + newargs += list_newvars() + appended = True else: newargs.append(arg) link.args[:] = newargs @@ -271,20 +272,24 @@ for block, vars in variables_by_block.items(): # look for variables arriving from outside the block - for var in vars: - if var in block.inputargs: - i = block.inputargs.index(var) - newinputargs = block.inputargs[:i] - newvarsmap = {} - for key in self.flatnames: - newvar = Variable() - newvar.concretetype = self.newvarstype[key] - newvarsmap[key] = newvar - newinputargs.append(newvar) - newinputargs += block.inputargs[i+1:] - block.inputargs[:] = newinputargs - assert var not in block.inputargs - self.flowin(block, count, var, newvarsmap) + newvarsmap = None + newinputargs = [] + inputvars = {} + for var in block.inputargs: + if var in vars: + inputvars[var] = None + if newvarsmap is None: + newvarsmap = {} + for key in self.flatnames: + newvar = Variable() + newvar.concretetype = self.newvarstype[key] + newvarsmap[key] = newvar + newinputargs.append(newvar) + else: + newinputargs.append(var) + block.inputargs[:] = newinputargs + if inputvars: + self.flowin(block, count, inputvars, newvarsmap) # look for variables created inside the block by a malloc vars_created_here = [] @@ -292,7 +297,7 @@ if self.check_malloc(op) and op.result in vars: vars_created_here.append(op.result) for var in vars_created_here: - self.flowin(block, count, var, newvarsmap=None) + self.flowin(block, count, {var: True}, newvarsmap=None) return count[0] @@ -486,7 +491,6 @@ newvarsmap[key] = op.args[2] self.last_removed_access = len(self.newops) elif op.opname in ("same_as", "cast_pointer"): - assert op.result not in vars vars[op.result] = True # Consider the two pointers (input and result) as # equivalent. We can, and indeed must, use the same @@ -605,7 +609,6 @@ newvarsmap[key] = op.args[2] last_removed_access = len(self.newops) elif op.opname in ("same_as", "oodowncast", "ooupcast"): - assert op.result not in vars vars[op.result] = True # Consider the two pointers (input and result) as # equivalent. We can, and indeed must, use the same Modified: pypy/branch/smalltalk-shadow-changes/pypy/translator/backendopt/test/test_malloc.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/translator/backendopt/test/test_malloc.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/translator/backendopt/test/test_malloc.py Fri May 23 16:22:38 2008 @@ -335,7 +335,6 @@ assert link.prevblock.operations[-1].opname == 'keepalive' def test_nested_struct(self): - py.test.skip("XXX fix me!") S = lltype.GcStruct("S", ('x', lltype.Signed)) T = lltype.GcStruct("T", ('s', S)) def f(x): From fijal at codespeak.net Fri May 23 16:41:32 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 23 May 2008 16:41:32 +0200 (CEST) Subject: [pypy-svn] r55150 - in pypy/branch/js-refactoring/pypy/lang/js: . test/ecma Message-ID: <20080523144132.532B31684E9@codespeak.net> Author: fijal Date: Fri May 23 16:41:31 2008 New Revision: 55150 Modified: pypy/branch/js-refactoring/pypy/lang/js/baseop.py pypy/branch/js-refactoring/pypy/lang/js/interpreter.py pypy/branch/js-refactoring/pypy/lang/js/jsobj.py pypy/branch/js-refactoring/pypy/lang/js/test/ecma/conftest.py Log: * Use overloaded eval for tests * Fix few bugs * *All* Number tests passes these days. Modified: pypy/branch/js-refactoring/pypy/lang/js/baseop.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/baseop.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/baseop.py Fri May 23 16:41:31 2008 @@ -144,7 +144,8 @@ return x.ToString(ctx) == y.ToString(ctx) elif type1 == "boolean": return x.ToBoolean() == x.ToBoolean() - return x == y + # XXX rethink it here + return x.ToString(ctx) == y.ToString(ctx) else: #step 14 if (type1 == "undefined" and type2 == "null") or \ Modified: pypy/branch/js-refactoring/pypy/lang/js/interpreter.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/interpreter.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/interpreter.py Fri May 23 16:41:31 2008 @@ -81,7 +81,7 @@ class W_StringObject(W_NativeObject): def Call(self, ctx, args=[], this=None): - if len(args) >= 1 and not isnull_or_undefined(args[0]): + if len(args) >= 1: return W_String(args[0].ToString(ctx)) else: return W_String('') @@ -97,7 +97,7 @@ proto = ctx.get_global().Get('Array').Get('prototype') array = W_Array(ctx, Prototype=proto, Class = proto.Class) for i in range(len(args)): - array.Put(str(i), args[0]) + array.Put(str(i), args[i]) return array def Construct(self, ctx, args=[]): @@ -317,13 +317,19 @@ class W_ValueToString(W_NewBuiltin): "this is the toString function for objects with Value" def Call(self, ctx, args=[], this=None): + if this.Value.type() != 'number': + raise JsTypeError('Wrong type') return W_String(this.Value.ToString(ctx)) - -class W_ValueValueOf(W_NewBuiltin): - "this is the valueOf function for objects with Value" - def Call(self, ctx, args=[], this=None): - return this.Value +def get_value_of(type, ctx): + class W_ValueValueOf(W_NewBuiltin): + "this is the valueOf function for objects with Value" + def Call(self, ctx, args=[], this=None): + if type != this.Class: + raise JsTypeError('%s.prototype.valueOf called with incompatible type' % self.type()) + return this.Value + return W_ValueValueOf(ctx) + class W_CharAt(W_NewBuiltin): def Call(self, ctx, args=[], this=None): string = this.ToString(ctx) @@ -452,7 +458,7 @@ 'constructor': w_FncPrototype, '__proto__': w_BoolPrototype, 'toString': W_ValueToString(ctx), - 'valueOf': W_ValueValueOf(ctx), + 'valueOf': get_value_of('Boolean', ctx) }) w_Boolean.Put('prototype', w_BoolPrototype) @@ -462,18 +468,22 @@ #Number w_Number = W_NumberObject('Number', w_FncPrototype) + w_empty_fun = w_Function.Call(ctx, args=[W_String('')]) + w_NumPrototype = create_object(ctx, 'Object', Value=W_FloatNumber(0.0)) w_NumPrototype.Class = 'Number' put_values(w_NumPrototype, { - 'constructor': w_FncPrototype, - '__proto__': w_NumPrototype, + 'constructor': w_Number, + '__proto__': w_empty_fun, 'toString': W_ValueToString(ctx), - 'valueOf': W_ValueValueOf(ctx), + 'valueOf': get_value_of('Number', ctx), }) put_values(w_Number, { 'constructor': w_FncPrototype, 'prototype': w_NumPrototype, + '__proto__': w_empty_fun, + 'length' : W_IntNumber(1), }) w_Number.propdict['prototype'].ro = True w_Number.Put('MAX_VALUE', W_FloatNumber(1.7976931348623157e308), @@ -500,7 +510,7 @@ 'constructor': w_FncPrototype, '__proto__': w_StrPrototype, 'toString': W_ValueToString(ctx), - 'valueOf': W_ValueValueOf(ctx), + 'valueOf': get_value_of('String', ctx), 'charAt': W_CharAt(ctx), 'concat': W_Concat(ctx), 'indexOf': W_IndexOf(ctx), Modified: pypy/branch/js-refactoring/pypy/lang/js/jsobj.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/jsobj.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/jsobj.py Fri May 23 16:41:31 2008 @@ -59,7 +59,7 @@ def Put(self, P, V, dd=False, ro=False, de=False, it=False): - raise NotImplementedError + pass def PutValue(self, w, ctx): pass @@ -99,6 +99,9 @@ def ToBoolean(self): return False + def ToString(self, ctx): + return "null" + def type(self): return 'null' @@ -261,7 +264,7 @@ raise NotImplementedError def type(self): - return 'builtin' + return self.Class class W_Builtin(W_PrimitiveObject): def __init__(self, builtin=None, ctx=None, Prototype=None, Class='function', @@ -612,37 +615,6 @@ jsproperty = Property('', w_Undefined)) return ctx -# class W_Reference(W_Root): -# """Reference Type""" -# def __init__(self, property_name, base=None): -# self.base = base -# self.property_name = property_name - -# def check_empty(self): -# if self.base is None: -# exception = "ReferenceError: %s is not defined"%(self.property_name,) -# raise ThrowException(W_String(exception)) - -# #def GetValue(self): -# # self.check_empty() -# # return self.base.Get(self.property_name) - -# #def PutValue(self, w, ctx): -# # base = self.base -# # if base is None: -# # base = ctx.scope[-1] -# # base.Put(self.property_name, w) -# # return w - -# #def GetBase(self): -# # return self.base - -# #def GetPropertyName(self): -# # return self.property_name - -# def __str__(self): -# return "<" + str(self.base) + " -> " + str(self.property_name) + ">" - class W_Iterator(W_Root): def __init__(self, elements_w): self.elements_w = elements_w Modified: pypy/branch/js-refactoring/pypy/lang/js/test/ecma/conftest.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/test/ecma/conftest.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/test/ecma/conftest.py Fri May 23 16:41:31 2008 @@ -1,6 +1,6 @@ import py from pypy.lang.js.interpreter import * -from pypy.lang.js.jsobj import W_Array +from pypy.lang.js.jsobj import W_Array, W_String from pypy.rlib.parsing.parsing import ParseError from py.__.test.outcome import Failed, ExceptionFailure import pypy.lang.js as js @@ -12,6 +12,12 @@ rootdir = py.magic.autopath().dirpath() exclusionlist = ['shell.js', 'browser.js'] +def overriden_evaljs(ctx, args, this): + try: + return evaljs(ctx, args, this) + except JsBaseExcept: + return W_String("error") + class JSDirectory(py.test.collect.Directory): def filefilter(self, path): @@ -27,8 +33,6 @@ if p.check(file=1): return JSTestFile(p, parent=self) - - class JSTestFile(py.test.collect.Module): def init_interp(cls): if hasattr(cls, 'interp'): @@ -42,6 +46,9 @@ cls.interp.run(cls.shellfile) cls.testcases = cls.interp.global_context.resolve_identifier('testcases') cls.tc = cls.interp.global_context.resolve_identifier('tc') + # override eval + cls.interp.global_context.put('eval', W_Builtin(overriden_evaljs)) + init_interp = classmethod(init_interp) def __init__(self, fspath, parent=None): From antocuni at codespeak.net Fri May 23 19:08:48 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 23 May 2008 19:08:48 +0200 (CEST) Subject: [pypy-svn] r55153 - in pypy/branch/oo-jit/pypy/translator: cli cli/src cli/test oosupport Message-ID: <20080523170848.4E232168401@codespeak.net> Author: antocuni Date: Fri May 23 19:08:46 2008 New Revision: 55153 Modified: pypy/branch/oo-jit/pypy/translator/cli/cts.py pypy/branch/oo-jit/pypy/translator/cli/src/pypylib.cs pypy/branch/oo-jit/pypy/translator/cli/test/test_dict.py pypy/branch/oo-jit/pypy/translator/oosupport/constant.py Log: implement dict with void key for gencli; this allows jit/codegen/cli/test_gencli_portal/test_main_as_portal to pass, but it seems that such dicts are not really supported by rpython, as you can see by uncommeting the test in test_dict or moving the tests to rpython/test/test_rdict :-( Modified: pypy/branch/oo-jit/pypy/translator/cli/cts.py ============================================================================== --- pypy/branch/oo-jit/pypy/translator/cli/cts.py (original) +++ pypy/branch/oo-jit/pypy/translator/cli/cts.py Fri May 23 19:08:46 2008 @@ -129,6 +129,7 @@ WEAKREF = types.weakref.classname() PYPY_DICT_OF_VOID = '[pypylib]pypy.runtime.DictOfVoid`2<%s, int32>' +PYPY_DICT_OF_VOID_KEY = '[pypylib]pypy.runtime.DictOfVoidKey`2' _lltype_to_cts = { @@ -277,6 +278,9 @@ else: # XXX return CliClassType(None, PYPY_DICT_OF_VOID % key_type) + elif key_type == types.void: + assert value_type != types.void + return CliClassType(None, PYPY_DICT_OF_VOID_KEY % value_type) return types.dict.specialize(key_type, value_type) elif isinstance(t, ootype.DictItemsIterator): key_type = self.lltype_to_cts(t._KEYTYPE) Modified: pypy/branch/oo-jit/pypy/translator/cli/src/pypylib.cs ============================================================================== --- pypy/branch/oo-jit/pypy/translator/cli/src/pypylib.cs (original) +++ pypy/branch/oo-jit/pypy/translator/cli/src/pypylib.cs Fri May 23 19:08:46 2008 @@ -593,6 +593,43 @@ } } + // it assumes TKey is a placeholder, it's not really used + public class DictOfVoidKey + { + private int length = 0; + private TValue elem = default(TValue); + + public DictOfVoidKey() {} + + public int ll_length() { return this.length; } + public TValue ll_get() { return this.elem; } + + public void ll_set(TValue value) { + this.length = 1; + this.elem = value; + } + + public bool ll_remove() { + if (this.length > 0) { + this.length = 0; + return true; + } + return false; + } + + public bool ll_contains() { return (this.length > 0); } + public void ll_contains_get() { } + public void ll_clear() { this.length = 0; } + + public DictItemsIterator ll_get_items_iterator() + { + List> foo = new List>(); + if (length == 1) + foo.Add(new KeyValuePair(default(TKey), this.elem)); + return new DictItemsIterator(foo.GetEnumerator()); + } + } + public class DictVoidVoid { private int length = 0; Modified: pypy/branch/oo-jit/pypy/translator/cli/test/test_dict.py ============================================================================== --- pypy/branch/oo-jit/pypy/translator/cli/test/test_dict.py (original) +++ pypy/branch/oo-jit/pypy/translator/cli/test/test_dict.py Fri May 23 19:08:46 2008 @@ -17,6 +17,26 @@ return d[0] assert self.interpret(fn, [2]) is None + def test_dict_with_void_key(self): + def fn(flag): + d = {} + if flag: + d[None] = flag + return bool(d) + res = self.interpret(fn, [42]) + assert res is True + +## XXX: it fails because of a bug in the annotator, which thinks the +## last line always raises +## def test_dict_with_void_key_pbc(self): +## d = {} +## def fn(flag): +## if flag: +## d[None] = flag +## return d[None] +## res = self.interpret(fn, [42], backendopt=False) +## assert res == 42 + class TestCliEmptyDict(CliTest, oodict.BaseTestEmptyDict): pass Modified: pypy/branch/oo-jit/pypy/translator/oosupport/constant.py ============================================================================== --- pypy/branch/oo-jit/pypy/translator/oosupport/constant.py (original) +++ pypy/branch/oo-jit/pypy/translator/oosupport/constant.py Fri May 23 19:08:46 2008 @@ -709,8 +709,7 @@ gen.add_comment('Initializing dictionary constant') - if KEYTYPE is ootype.Void: - assert VALUETYPE is ootype.Void + if KEYTYPE is ootype.Void and VALUETYPE is ootype.Void: return for key, value in self.value._dict.iteritems(): From antocuni at codespeak.net Fri May 23 19:35:48 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 23 May 2008 19:35:48 +0200 (CEST) Subject: [pypy-svn] r55154 - pypy/dist/pypy/translator/cli Message-ID: <20080523173548.7EAB916840E@codespeak.net> Author: antocuni Date: Fri May 23 19:35:47 2008 New Revision: 55154 Modified: pypy/dist/pypy/translator/cli/ilgenerator.py Log: fix translation Modified: pypy/dist/pypy/translator/cli/ilgenerator.py ============================================================================== --- pypy/dist/pypy/translator/cli/ilgenerator.py (original) +++ pypy/dist/pypy/translator/cli/ilgenerator.py Fri May 23 19:35:47 2008 @@ -415,6 +415,9 @@ else: assert False, "Unexpected constant type" + def push_null(self, TYPE): + self.ilasm.opcode('ldnull') + def dup(self, TYPE): self.ilasm.opcode('dup') From santagada at codespeak.net Fri May 23 20:19:02 2008 From: santagada at codespeak.net (santagada at codespeak.net) Date: Fri, 23 May 2008 20:19:02 +0200 (CEST) Subject: [pypy-svn] r55155 - pypy/branch/js-refactoring/pypy/lang/js Message-ID: <20080523181902.433FD168427@codespeak.net> Author: santagada Date: Fri May 23 20:18:59 2008 New Revision: 55155 Modified: pypy/branch/js-refactoring/pypy/lang/js/interpreter.py Log: each toString function should have it's own restriction to type Modified: pypy/branch/js-refactoring/pypy/lang/js/interpreter.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/interpreter.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/interpreter.py Fri May 23 20:18:59 2008 @@ -316,11 +316,23 @@ class W_ValueToString(W_NewBuiltin): "this is the toString function for objects with Value" + mytype = '' def Call(self, ctx, args=[], this=None): - if this.Value.type() != 'number': + if this.Value.type() != self.mytype: raise JsTypeError('Wrong type') return W_String(this.Value.ToString(ctx)) + +class W_NumberValueToString(W_ValueToString): + mytype = 'number' + +class W_BooleanValueToString(W_ValueToString): + mytype = 'boolean' + +class W_StringValueToString(W_ValueToString): + mytype = 'string' + + def get_value_of(type, ctx): class W_ValueValueOf(W_NewBuiltin): "this is the valueOf function for objects with Value" @@ -457,7 +469,7 @@ put_values(w_BoolPrototype, { 'constructor': w_FncPrototype, '__proto__': w_BoolPrototype, - 'toString': W_ValueToString(ctx), + 'toString': W_BooleanValueToString(ctx), 'valueOf': get_value_of('Boolean', ctx) }) @@ -475,7 +487,7 @@ put_values(w_NumPrototype, { 'constructor': w_Number, '__proto__': w_empty_fun, - 'toString': W_ValueToString(ctx), + 'toString': W_NumberValueToString(ctx), 'valueOf': get_value_of('Number', ctx), }) @@ -509,7 +521,7 @@ put_values(w_StrPrototype, { 'constructor': w_FncPrototype, '__proto__': w_StrPrototype, - 'toString': W_ValueToString(ctx), + 'toString': W_StringValueToString(ctx), 'valueOf': get_value_of('String', ctx), 'charAt': W_CharAt(ctx), 'concat': W_Concat(ctx), From santagada at codespeak.net Fri May 23 20:20:46 2008 From: santagada at codespeak.net (santagada at codespeak.net) Date: Fri, 23 May 2008 20:20:46 +0200 (CEST) Subject: [pypy-svn] r55156 - pypy/branch/js-refactoring/pypy/lang/js/test Message-ID: <20080523182046.BB9DA16842A@codespeak.net> Author: santagada Date: Fri May 23 20:20:45 2008 New Revision: 55156 Modified: pypy/branch/js-refactoring/pypy/lang/js/test/test_interp.py Log: a small bug in the tests, null should print null and not a empty string, this fixes all base tests Modified: pypy/branch/js-refactoring/pypy/lang/js/test/test_interp.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/test/test_interp.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/test/test_interp.py Fri May 23 20:20:45 2008 @@ -404,7 +404,7 @@ print(null); print(-z); """, ['10', '2', 'false', '3', 'NaN', 'Infinity', '-Infinity', - '3', '', '-2']) + '3', 'null', '-2']) def test_globalproperties(): assertp( """ From fijal at codespeak.net Fri May 23 23:36:14 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 23 May 2008 23:36:14 +0200 (CEST) Subject: [pypy-svn] r55157 - pypy/dist/pypy/rlib/rstruct Message-ID: <20080523213614.41147498019@codespeak.net> Author: fijal Date: Fri May 23 23:36:13 2008 New Revision: 55157 Added: pypy/dist/pypy/rlib/rstruct/ pypy/dist/pypy/rlib/rstruct/__init__.py (contents, props changed) Log: Create a directory for a single place where we can keep various struct-related informations and helpers. Added: pypy/dist/pypy/rlib/rstruct/__init__.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rlib/rstruct/__init__.py Fri May 23 23:36:13 2008 @@ -0,0 +1,2 @@ + +from struct import pack, unpack From fijal at codespeak.net Fri May 23 23:54:51 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 23 May 2008 23:54:51 +0200 (CEST) Subject: [pypy-svn] r55158 - pypy/dist/pypy/objspace/std/test Message-ID: <20080523215451.D1F6F168515@codespeak.net> Author: fijal Date: Fri May 23 23:54:48 2008 New Revision: 55158 Modified: pypy/dist/pypy/objspace/std/test/test_dictmultiobject.py Log: This tests are failing for multidict, skip by now. Modified: pypy/dist/pypy/objspace/std/test/test_dictmultiobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/test/test_dictmultiobject.py (original) +++ pypy/dist/pypy/objspace/std/test/test_dictmultiobject.py Fri May 23 23:54:48 2008 @@ -31,6 +31,8 @@ def test_emptydict_unhashable(self): raises(TypeError, "{}[['x']]") + def test_repr_with_overriden_items(self): + skip("XXX broken!!!") class TestW_DictSharing(test_dictobject.TestW_DictObject): def setup_class(cls): @@ -58,6 +60,9 @@ a.__dict__.items() == [("abc", 12)] + def test_repr_with_overriden_items(self): + skip("XXX broken!!!") + class TestW_DictSmall(test_dictobject.TestW_DictObject): def setup_class(cls): cls.space = gettestobjspace(**{"objspace.std.withsmalldicts": True}) @@ -66,6 +71,9 @@ def setup_class(cls): cls.space = gettestobjspace(**{"objspace.std.withsmalldicts": True}) + def test_repr_with_overriden_items(self): + skip("XXX broken!!!") + class C: pass class FakeSpace(test_dictobject.FakeSpace): From cfbolz at codespeak.net Sat May 24 00:00:55 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sat, 24 May 2008 00:00:55 +0200 (CEST) Subject: [pypy-svn] r55159 - in pypy/dist/pypy/objspace/std: . test Message-ID: <20080523220055.0F267168515@codespeak.net> Author: cfbolz Date: Sat May 24 00:00:49 2008 New Revision: 55159 Modified: pypy/dist/pypy/objspace/std/dictmultiobject.py pypy/dist/pypy/objspace/std/test/test_dictmultiobject.py Log: fixing the bug is less work than skipping the tests Modified: pypy/dist/pypy/objspace/std/dictmultiobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/dictmultiobject.py (original) +++ pypy/dist/pypy/objspace/std/dictmultiobject.py Sat May 24 00:00:49 2008 @@ -1271,7 +1271,7 @@ # XXX for now, we cannot use iteritems() at app-level because # we want a reasonable result instead of a RuntimeError # even if the dict is mutated by the repr() in the loop. - for k, v in d.items(): + for k, v in dict.items(d): items.append(repr(k) + ": " + repr(v)) return "{" + ', '.join(items) + "}" finally: Modified: pypy/dist/pypy/objspace/std/test/test_dictmultiobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/test/test_dictmultiobject.py (original) +++ pypy/dist/pypy/objspace/std/test/test_dictmultiobject.py Sat May 24 00:00:49 2008 @@ -31,8 +31,6 @@ def test_emptydict_unhashable(self): raises(TypeError, "{}[['x']]") - def test_repr_with_overriden_items(self): - skip("XXX broken!!!") class TestW_DictSharing(test_dictobject.TestW_DictObject): def setup_class(cls): @@ -60,8 +58,6 @@ a.__dict__.items() == [("abc", 12)] - def test_repr_with_overriden_items(self): - skip("XXX broken!!!") class TestW_DictSmall(test_dictobject.TestW_DictObject): def setup_class(cls): @@ -71,8 +67,6 @@ def setup_class(cls): cls.space = gettestobjspace(**{"objspace.std.withsmalldicts": True}) - def test_repr_with_overriden_items(self): - skip("XXX broken!!!") class C: pass From fijal at codespeak.net Sat May 24 00:02:33 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 24 May 2008 00:02:33 +0200 (CEST) Subject: [pypy-svn] r55161 - pypy/dist/pypy/doc/discussion Message-ID: <20080523220233.38648168515@codespeak.net> Author: fijal Date: Sat May 24 00:02:32 2008 New Revision: 55161 Removed: pypy/dist/pypy/doc/discussion/build-tool-web-frontend.txt Log: I think this can go away now, as build tool is not going anywhere From fijal at codespeak.net Sat May 24 00:08:20 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 24 May 2008 00:08:20 +0200 (CEST) Subject: [pypy-svn] r55162 - in pypy/dist/pypy/rlib/rsdl: . test Message-ID: <20080523220820.C145B16854A@codespeak.net> Author: fijal Date: Sat May 24 00:08:19 2008 New Revision: 55162 Modified: pypy/dist/pypy/rlib/rsdl/RMix.py (props changed) pypy/dist/pypy/rlib/rsdl/RSDL_helper.py (props changed) pypy/dist/pypy/rlib/rsdl/test/test_sdl_mixer.py (props changed) pypy/dist/pypy/rlib/rsdl/test/test_surface.py (props changed) Log: Fixeol From fijal at codespeak.net Sat May 24 00:08:50 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 24 May 2008 00:08:50 +0200 (CEST) Subject: [pypy-svn] r55163 - pypy/dist/pypy/rlib/rstruct Message-ID: <20080523220850.52A2C16854C@codespeak.net> Author: fijal Date: Sat May 24 00:08:48 2008 New Revision: 55163 Added: pypy/dist/pypy/rlib/rstruct/error.py - copied, changed from r55150, pypy/dist/pypy/module/struct/error.py pypy/dist/pypy/rlib/rstruct/ieee.py - copied unchanged from r55150, pypy/dist/pypy/module/struct/ieee.py pypy/dist/pypy/rlib/rstruct/nativefmttable.py - copied, changed from r55150, pypy/dist/pypy/module/struct/nativefmttable.py pypy/dist/pypy/rlib/rstruct/standardfmttable.py - copied, changed from r55150, pypy/dist/pypy/module/struct/standardfmttable.py pypy/dist/pypy/rlib/rstruct/unichar.py - copied unchanged from r55150, pypy/dist/pypy/module/struct/unichar.py Modified: pypy/dist/pypy/rlib/rstruct/ (props changed) pypy/dist/pypy/rlib/rstruct/__init__.py Log: Factor out rpython-only pieces of struct module Modified: pypy/dist/pypy/rlib/rstruct/__init__.py ============================================================================== --- pypy/dist/pypy/rlib/rstruct/__init__.py (original) +++ pypy/dist/pypy/rlib/rstruct/__init__.py Sat May 24 00:08:48 2008 @@ -1,2 +1,14 @@ from struct import pack, unpack +from pypy.rpython.extregistry import ExtRegistryEntry + +class UnpackEntry(ExtRegistryEntry): + _about_ = unpack + + def compute_result_annotation(self, s_fmt, s_s): + from pypy.annotation import model as annmodel + if not isinstance(s_s, annmodel.SomeString): + raise TypeError("Got %s, string expected" % (s_s,)) + if not s_fmt.is_constant(): + raise ValueError("Can only use struct.unpack with first argument constant in RPython") + From fijal at codespeak.net Sat May 24 00:09:36 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 24 May 2008 00:09:36 +0200 (CEST) Subject: [pypy-svn] r55164 - pypy/dist/pypy/objspace/std/test Message-ID: <20080523220936.67E0D16854A@codespeak.net> Author: fijal Date: Sat May 24 00:09:35 2008 New Revision: 55164 Modified: pypy/dist/pypy/objspace/std/test/test_longobject.py Log: Skip this test, it's broken needs investigation Modified: pypy/dist/pypy/objspace/std/test/test_longobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/test/test_longobject.py (original) +++ pypy/dist/pypy/objspace/std/test/test_longobject.py Sat May 24 00:09:35 2008 @@ -24,6 +24,7 @@ space.raises_w(space.w_TypeError, space.bigint_w, w_obj) def test_rint_variants(self): + py.test.skip("XXX broken!") from pypy.rpython.tool.rfficache import platform space = self.space for r in platform.numbertype_to_rclass.values(): From fijal at codespeak.net Sat May 24 00:09:57 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 24 May 2008 00:09:57 +0200 (CEST) Subject: [pypy-svn] r55165 - pypy/dist/pypy/objspace/std Message-ID: <20080523220957.F0CD716854C@codespeak.net> Author: fijal Date: Sat May 24 00:09:53 2008 New Revision: 55165 Modified: pypy/dist/pypy/objspace/std/marshal_impl.py pypy/dist/pypy/objspace/std/ropeunicodeobject.py pypy/dist/pypy/objspace/std/unicodeobject.py Log: Fix imports Modified: pypy/dist/pypy/objspace/std/marshal_impl.py ============================================================================== --- pypy/dist/pypy/objspace/std/marshal_impl.py (original) +++ pypy/dist/pypy/objspace/std/marshal_impl.py Sat May 24 00:09:53 2008 @@ -18,7 +18,7 @@ from pypy.interpreter.special import Ellipsis from pypy.interpreter.pycode import PyCode from pypy.interpreter import gateway -from pypy.module.struct import ieee +from pypy.rlib.rstruct import ieee from pypy.objspace.std.boolobject import W_BoolObject from pypy.objspace.std.complexobject import W_ComplexObject Modified: pypy/dist/pypy/objspace/std/ropeunicodeobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/ropeunicodeobject.py (original) +++ pypy/dist/pypy/objspace/std/ropeunicodeobject.py Sat May 24 00:09:53 2008 @@ -910,8 +910,7 @@ return mod_format(space, w_format, w_values, do_unicode=True) def buffer__RopeUnicode(space, w_unicode): - # xxx this is a slightly strange thing... - from pypy.module.struct.unichar import pack_unichar + from pypy.rlib.rstruct.unichar import pack_unichar charlist = [] node = w_unicode._node iter = rope.ItemIterator(node) Modified: pypy/dist/pypy/objspace/std/unicodeobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/unicodeobject.py (original) +++ pypy/dist/pypy/objspace/std/unicodeobject.py Sat May 24 00:09:53 2008 @@ -944,8 +944,7 @@ return mod_format(space, w_format, w_values, do_unicode=True) def buffer__Unicode(space, w_unicode): - # xxx this is a slightly strange thing... - from pypy.module.struct.unichar import pack_unichar + from pypy.rlib.rstruct.unichar import pack_unichar charlist = [] for unich in w_unicode._value: pack_unichar(unich, charlist) From fijal at codespeak.net Sat May 24 00:10:41 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 24 May 2008 00:10:41 +0200 (CEST) Subject: [pypy-svn] r55166 - in pypy/dist/pypy/module/struct: . test Message-ID: <20080523221041.C2CD9168551@codespeak.net> Author: fijal Date: Sat May 24 00:10:40 2008 New Revision: 55166 Removed: pypy/dist/pypy/module/struct/error.py pypy/dist/pypy/module/struct/ieee.py pypy/dist/pypy/module/struct/nativefmttable.py pypy/dist/pypy/module/struct/standardfmttable.py pypy/dist/pypy/module/struct/test/test_ieee.py pypy/dist/pypy/module/struct/unichar.py Modified: pypy/dist/pypy/module/struct/formatiterator.py pypy/dist/pypy/module/struct/interp_struct.py pypy/dist/pypy/module/struct/test/test_struct.py Log: Remove rpython-only parts (moved to rlib/struct), fix imports Modified: pypy/dist/pypy/module/struct/formatiterator.py ============================================================================== --- pypy/dist/pypy/module/struct/formatiterator.py (original) +++ pypy/dist/pypy/module/struct/formatiterator.py Sat May 24 00:10:40 2008 @@ -3,11 +3,11 @@ from pypy.rlib.unroll import unrolling_iterable from pypy.rlib.rarithmetic import ovfcheck -from pypy.module.struct.error import StructError -from pypy.module.struct.standardfmttable import standard_fmttable -from pypy.module.struct.standardfmttable import PACK_ACCEPTS_BROKEN_INPUT -from pypy.module.struct.nativefmttable import native_fmttable -from pypy.module.struct.nativefmttable import native_is_bigendian +from pypy.rlib.rstruct.error import StructError +from pypy.rlib.rstruct.standardfmttable import standard_fmttable +from pypy.rlib.rstruct.standardfmttable import PACK_ACCEPTS_BROKEN_INPUT +from pypy.rlib.rstruct.nativefmttable import native_fmttable +from pypy.rlib.rstruct.nativefmttable import native_is_bigendian class FormatIterator(object): Modified: pypy/dist/pypy/module/struct/interp_struct.py ============================================================================== --- pypy/dist/pypy/module/struct/interp_struct.py (original) +++ pypy/dist/pypy/module/struct/interp_struct.py Sat May 24 00:10:40 2008 @@ -1,6 +1,6 @@ from pypy.interpreter.gateway import ObjSpace from pypy.interpreter.error import OperationError -from pypy.module.struct.error import StructError +from pypy.rlib.rstruct.error import StructError from pypy.module.struct.formatiterator import CalcSizeFormatIterator from pypy.module.struct.formatiterator import PackFormatIterator from pypy.module.struct.formatiterator import UnpackFormatIterator Modified: pypy/dist/pypy/module/struct/test/test_struct.py ============================================================================== --- pypy/dist/pypy/module/struct/test/test_struct.py (original) +++ pypy/dist/pypy/module/struct/test/test_struct.py Sat May 24 00:10:40 2008 @@ -4,7 +4,7 @@ import py from pypy.conftest import gettestobjspace -from pypy.module.struct.nativefmttable import native_is_bigendian +from pypy.rlib.rstruct.nativefmttable import native_is_bigendian class AppTestStruct(object): From fijal at codespeak.net Sat May 24 00:12:05 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 24 May 2008 00:12:05 +0200 (CEST) Subject: [pypy-svn] r55167 - pypy/dist/pypy/module/zipimport Message-ID: <20080523221205.9B36016854D@codespeak.net> Author: fijal Date: Sat May 24 00:12:03 2008 New Revision: 55167 Modified: pypy/dist/pypy/module/zipimport/interp_zipimport.py Log: this is not needed to pass around Modified: pypy/dist/pypy/module/zipimport/interp_zipimport.py ============================================================================== --- pypy/dist/pypy/module/zipimport/interp_zipimport.py (original) +++ pypy/dist/pypy/module/zipimport/interp_zipimport.py Sat May 24 00:12:03 2008 @@ -25,11 +25,10 @@ (False, False, '.py')]) class W_ZipImporter(Wrappable): - def __init__(self, space, name, w_dir, w_zipfile, prefix): + def __init__(self, space, name, w_dir, prefix): self.space = space self.name = name self.w_dir = w_dir - self.w_zipfile = w_zipfile self.prefix = prefix def getprefix(space, self): @@ -240,7 +239,7 @@ except OperationError, e: # we catch everything as this function raise OperationError(space.w_ImportError, space.wrap( "%s seems not to be a zipfile" % (filename,))) - w_result = space.wrap(W_ZipImporter(space, name, w_dir, w_zipfile, prefix)) + w_result = space.wrap(W_ZipImporter(space, name, w_dir, prefix)) space.setitem(w_zip_cache, space.wrap(name), w_result) return w_result From fijal at codespeak.net Sat May 24 00:16:47 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 24 May 2008 00:16:47 +0200 (CEST) Subject: [pypy-svn] r55168 - pypy/dist/pypy/module/zipimport/test Message-ID: <20080523221647.1B2CB16854D@codespeak.net> Author: fijal Date: Sat May 24 00:16:46 2008 New Revision: 55168 Added: pypy/dist/pypy/module/zipimport/test/test_undocumented.py (contents, props changed) Log: Test for some undocumented features (haha!), actually completely broken, stolen from Brett Cannon and modified to fit into 2.4 syntax Added: pypy/dist/pypy/module/zipimport/test/test_undocumented.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/module/zipimport/test/test_undocumented.py Sat May 24 00:16:46 2008 @@ -0,0 +1,130 @@ +import zipimport +import py + +import os +import py_compile +import shutil +import time +import zipfile +from pypy.conftest import gettestobjspace + +example_code = 'attr = None' + +created_paths = set(['_top_level', + os.path.join('_pkg', '__init__'), + os.path.join('_pkg', 'submodule'), + os.path.join('_pkg', '_subpkg', '__init__'), + os.path.join('_pkg', '_subpkg', 'submodule') + ]) + +py.test.skip("Completely broken") + +def temp_zipfile(source=True, bytecode=True): + """Create a temporary zip file for testing. + + Clears zipimport._zip_directory_cache. + + """ + zipimport._zip_directory_cache = {} + zip_path = test_support.TESTFN + '.zip' + bytecode_suffix = 'c' if __debug__ else 'o' + zip_file = zipfile.ZipFile(zip_path, 'w') + try: + for path in created_paths: + if os.sep in path: + directory = os.path.split(path)[0] + if not os.path.exists(directory): + os.makedirs(directory) + code_path = path + '.py' + try: + temp_file = open(code_path, 'w') + temp_file.write(example_code) + finally: + temp_file.close() + if source: + zip_file.write(code_path) + if bytecode: + py_compile.compile(code_path, doraise=True) + zip_file.write(code_path + bytecode_suffix) + zip_file.close() + yield os.path.abspath(zip_path) + finally: + zip_file.close() + for path in created_paths: + if os.sep in path: + directory = os.path.split(path)[0] + if os.path.exists(directory): + shutil.rmtree(directory) + else: + for suffix in ('.py', '.py' + bytecode_suffix): + test_support.unlink(path + suffix) + test_support.unlink(zip_path) + + +class AppTestZipImport: + def setup_class(cls): + space = gettestobjspace(usemodules=['zipimport', 'zlib', 'rctime']) + cls.space = space + + def test_inheritance(self): + # Should inherit from ImportError. + import zipimport + assert issubclass(zipimport.ZipImportError, ImportError) + + def test_nonzip(self): + # ZipImportError should be raised if a non-zip file is specified. + try: + test_file = open(test_support.TESTFN, 'w') + test_file.write("# Test file for zipimport.") + try: + raises(zipimport.ZipImportError, + zipimport.zipimporter, test_support.TESTFN) + finally: + test_support.unlink(test_support.TESTFN) + finally: + test_file.close() + + def test_root(self): + raises(zipimport.ZipImportError, zipimport.zipimporter, + os.sep) + + + def test_direct_path(self): + # A zipfile should return an instance of zipimporter. + try: + zip_path = temp_zipfile() + zip_importer = zipimport.zipimporter(zip_path) + assert isinstance(zip_importer, zipimport.zipimporter) + assert zip_importer.archive == zip_path + assert zip_importer.prefix == '' + assert zip_path in zipimport._zip_directory_cache + finally: + zip_path.close() + + def test_pkg_path(self): + # Thanks to __path__, need to be able to work off of a path with a zip + # file at the front and a path for the rest. + try: + zip_path = temp_zipfile() + prefix = '_pkg' + path = os.path.join(zip_path, prefix) + zip_importer = zipimport.zipimporter(path) + assert isinstance(zip_importer, zipimport.zipimporter) + assert zip_importer.archive == zip_path + assert zip_importer.prefix == prefix + assert zip_path in zipimport._zip_directory_cache + finally: + zip_path.close() + + def test_zip_directory_cache(self): + # Test that _zip_directory_cache is set properly. + # Using a package entry to test using a hard example. + try: + zip_path = temp_zipfile(bytecode=False) + importer = zipimport.zipimporter(os.path.join(zip_path, '_pkg')) + assert zip_path in zipimport._zip_directory_cache + file_set = set(zipimport._zip_directory_cache[zip_path].iterkeys()) + compare_set = set(path + '.py' for path in created_paths) + assert file_set == compare_set + finally: + zip_path.close() From fijal at codespeak.net Sat May 24 00:51:41 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sat, 24 May 2008 00:51:41 +0200 (CEST) Subject: [pypy-svn] r55169 - in pypy/dist/pypy: module/struct rlib/rstruct Message-ID: <20080523225141.3AC13168568@codespeak.net> Author: fijal Date: Sat May 24 00:51:38 2008 New Revision: 55169 Added: pypy/dist/pypy/rlib/rstruct/formatiterator.py (contents, props changed) Modified: pypy/dist/pypy/module/struct/formatiterator.py Log: Move pure-RPython parts of formatiterator to rstruct Modified: pypy/dist/pypy/module/struct/formatiterator.py ============================================================================== --- pypy/dist/pypy/module/struct/formatiterator.py (original) +++ pypy/dist/pypy/module/struct/formatiterator.py Sat May 24 00:51:38 2008 @@ -1,108 +1,10 @@ from pypy.interpreter.error import OperationError -from pypy.rlib.unroll import unrolling_iterable -from pypy.rlib.rarithmetic import ovfcheck from pypy.rlib.rstruct.error import StructError -from pypy.rlib.rstruct.standardfmttable import standard_fmttable from pypy.rlib.rstruct.standardfmttable import PACK_ACCEPTS_BROKEN_INPUT -from pypy.rlib.rstruct.nativefmttable import native_fmttable -from pypy.rlib.rstruct.nativefmttable import native_is_bigendian - - -class FormatIterator(object): - """ - An iterator-like object that follows format strings step by step. - It provides input to the packer/unpacker and accumulates their output. - The subclasses are specialized for either packing, unpacking, or - just computing the size. - """ - _mixin_ = True - _operate_is_specialized_ = False - - def interpret(self, fmt): - # decode the byte order, size and alignment based on the 1st char - table = unroll_native_fmtdescs - self.bigendian = native_is_bigendian - index = 0 - if len(fmt) > 0: - c = fmt[0] - index = 1 - if c == '@': - pass - elif c == '=': - table = unroll_standard_fmtdescs - elif c == '<': - table = unroll_standard_fmtdescs - self.bigendian = False - elif c == '>' or c == '!': - table = unroll_standard_fmtdescs - self.bigendian = True - else: - index = 0 - - # interpret the format string, - # calling self.operate() for each format unit - while index < len(fmt): - c = fmt[index] - index += 1 - if c.isspace(): - continue - if c.isdigit(): - repetitions = ord(c) - ord('0') - while True: - if index == len(fmt): - raise StructError("incomplete struct format") - c = fmt[index] - index += 1 - if not c.isdigit(): - break - try: - repetitions = ovfcheck(repetitions * 10) - repetitions = ovfcheck(repetitions + (ord(c) - - ord('0'))) - except OverflowError: - raise StructError("overflow in item count") - assert repetitions >= 0 - else: - repetitions = 1 - - for fmtdesc in table: - if c == fmtdesc.fmtchar: - if self._operate_is_specialized_: - if fmtdesc.alignment > 1: - self.align(fmtdesc.mask) - self.operate(fmtdesc, repetitions) - break - else: - raise StructError("bad char in struct format") - if not self._operate_is_specialized_: - if fmtdesc.alignment > 1: - self.align(fmtdesc.mask) - self.operate(fmtdesc, repetitions) - self.finished() - - def finished(self): - pass - - -class CalcSizeFormatIterator(FormatIterator): - totalsize = 0 - - def operate(self, fmtdesc, repetitions): - try: - size = ovfcheck(fmtdesc.size * repetitions) - self.totalsize = ovfcheck(self.totalsize + size) - except OverflowError: - raise StructError("total struct size too long") - - def align(self, mask): - pad = (-self.totalsize) & mask - try: - self.totalsize = ovfcheck(self.totalsize + pad) - except OverflowError: - raise StructError("total struct size too long") - +from pypy.rlib.rstruct.formatiterator import FormatIterator, \ + CalcSizeFormatIterator class PackFormatIterator(FormatIterator): @@ -245,24 +147,3 @@ self.result_w.append(self.space.wrap(value)) appendobj._annspecialcase_ = 'specialize:argtype(1)' - -class FmtDesc(object): - def __init__(self, fmtchar, attrs): - self.fmtchar = fmtchar - self.alignment = 1 # by default - self.needcount = False # by default - self.__dict__.update(attrs) - self.mask = self.alignment - 1 - assert self.alignment & self.mask == 0, ( - "this module assumes that all alignments are powers of two") - def _freeze_(self): - return True - -def table2desclist(table): - items = table.items() - items.sort() - lst = [FmtDesc(key, attrs) for key, attrs in items] - return unrolling_iterable(lst) - -unroll_standard_fmtdescs = table2desclist(standard_fmttable) -unroll_native_fmtdescs = table2desclist(native_fmttable) Added: pypy/dist/pypy/rlib/rstruct/formatiterator.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rlib/rstruct/formatiterator.py Sat May 24 00:51:38 2008 @@ -0,0 +1,122 @@ + +from pypy.rlib.rstruct.nativefmttable import native_is_bigendian +from pypy.rlib.unroll import unrolling_iterable +from pypy.rlib.rarithmetic import ovfcheck +from pypy.rlib.rstruct.error import StructError +from pypy.rlib.rstruct.standardfmttable import standard_fmttable +from pypy.rlib.rstruct.nativefmttable import native_fmttable + +class FormatIterator(object): + """ + An iterator-like object that follows format strings step by step. + It provides input to the packer/unpacker and accumulates their output. + The subclasses are specialized for either packing, unpacking, or + just computing the size. + """ + _mixin_ = True + _operate_is_specialized_ = False + + def interpret(self, fmt): + # decode the byte order, size and alignment based on the 1st char + table = unroll_native_fmtdescs + self.bigendian = native_is_bigendian + index = 0 + if len(fmt) > 0: + c = fmt[0] + index = 1 + if c == '@': + pass + elif c == '=': + table = unroll_standard_fmtdescs + elif c == '<': + table = unroll_standard_fmtdescs + self.bigendian = False + elif c == '>' or c == '!': + table = unroll_standard_fmtdescs + self.bigendian = True + else: + index = 0 + + # interpret the format string, + # calling self.operate() for each format unit + while index < len(fmt): + c = fmt[index] + index += 1 + if c.isspace(): + continue + if c.isdigit(): + repetitions = ord(c) - ord('0') + while True: + if index == len(fmt): + raise StructError("incomplete struct format") + c = fmt[index] + index += 1 + if not c.isdigit(): + break + try: + repetitions = ovfcheck(repetitions * 10) + repetitions = ovfcheck(repetitions + (ord(c) - + ord('0'))) + except OverflowError: + raise StructError("overflow in item count") + assert repetitions >= 0 + else: + repetitions = 1 + + for fmtdesc in table: + if c == fmtdesc.fmtchar: + if self._operate_is_specialized_: + if fmtdesc.alignment > 1: + self.align(fmtdesc.mask) + self.operate(fmtdesc, repetitions) + break + else: + raise StructError("bad char in struct format") + if not self._operate_is_specialized_: + if fmtdesc.alignment > 1: + self.align(fmtdesc.mask) + self.operate(fmtdesc, repetitions) + self.finished() + + def finished(self): + pass + +class CalcSizeFormatIterator(FormatIterator): + totalsize = 0 + + def operate(self, fmtdesc, repetitions): + try: + size = ovfcheck(fmtdesc.size * repetitions) + self.totalsize = ovfcheck(self.totalsize + size) + except OverflowError: + raise StructError("total struct size too long") + + def align(self, mask): + pad = (-self.totalsize) & mask + try: + self.totalsize = ovfcheck(self.totalsize + pad) + except OverflowError: + raise StructError("total struct size too long") + + +class FmtDesc(object): + def __init__(self, fmtchar, attrs): + self.fmtchar = fmtchar + self.alignment = 1 # by default + self.needcount = False # by default + self.__dict__.update(attrs) + self.mask = self.alignment - 1 + assert self.alignment & self.mask == 0, ( + "this module assumes that all alignments are powers of two") + def _freeze_(self): + return True + +def table2desclist(table): + items = table.items() + items.sort() + lst = [FmtDesc(key, attrs) for key, attrs in items] + return unrolling_iterable(lst) + + +unroll_standard_fmtdescs = table2desclist(standard_fmttable) +unroll_native_fmtdescs = table2desclist(native_fmttable) From cami at codespeak.net Sat May 24 15:05:37 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Sat, 24 May 2008 15:05:37 +0200 (CEST) Subject: [pypy-svn] r55191 - in pypy/dist/pypy/lang/gameboy: . test Message-ID: <20080524130537.DFD7A39B5C3@codespeak.net> Author: cami Date: Sat May 24 15:05:34 2008 New Revision: 55191 Modified: pypy/dist/pypy/lang/gameboy/cartridge.py pypy/dist/pypy/lang/gameboy/constants.py pypy/dist/pypy/lang/gameboy/cpu.py pypy/dist/pypy/lang/gameboy/gameboyImplementation.py pypy/dist/pypy/lang/gameboy/test/test_cpu.py pypy/dist/pypy/lang/gameboy/test/test_memory_bank_controller.py pypy/dist/pypy/lang/gameboy/test/test_rom.py Log: fixed some buggy tests added some cartridge memorbank tests Modified: pypy/dist/pypy/lang/gameboy/cartridge.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/cartridge.py (original) +++ pypy/dist/pypy/lang/gameboy/cartridge.py Sat May 24 15:05:34 2008 @@ -265,7 +265,7 @@ banks = int(len(buffer) / constants.ROM_BANK_SIZE) if banks < self.min_rom_bank_size or banks > self.max_rom_bank_size: raise Exception("Invalid ROM size %s, should be in [%s %s]" % \ - (hex(len(buffer)), hex(self.min_rom_bank_size), \ + (hex(banks), hex(self.min_rom_bank_size), \ hex(self.max_rom_bank_size))) self.rom = buffer self.rom_size = constants.ROM_BANK_SIZE * banks - 1 @@ -275,7 +275,7 @@ banks = int(len(buffer) / constants.RAM_BANK_SIZE) if banks < self.min_ram_bank_size or banks > self.max_ram_bank_size: raise Exception("Invalid RAM size %s, should be in [%s %s]" % \ - (hex(len(buffer)), hex(self.min_ram_bank_size), \ + (hex(banks), hex(self.min_ram_bank_size), \ hex(self.max_ram_bank_size))) self.ram = buffer self.ram_size = constants.RAM_BANK_SIZE * banks - 1 @@ -385,8 +385,8 @@ def __init__(self, rom, ram, clock_driver): MBC.__init__(self, rom, ram, clock_driver, - min_ram_bank_size=constants.RAM_BANK_SIZE, - max_ram_bank_size=constants.RAM_BANK_SIZE, + min_ram_bank_size=1, + max_ram_bank_size=1, min_rom_bank_size=2, max_rom_bank_size=16) Modified: pypy/dist/pypy/lang/gameboy/constants.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/constants.py (original) +++ pypy/dist/pypy/lang/gameboy/constants.py Sat May 24 15:05:34 2008 @@ -51,7 +51,7 @@ CHECKSUM_A_ADDRESS = 0x014E CHECKSUM_B_ADDRESS = 0x014F - #ROM Bank Size (16KB) +# ROM Bank Size (16KB) ROM_BANK_SIZE = 0x4000 # constants.RAM Bank Size (8KB) Modified: pypy/dist/pypy/lang/gameboy/cpu.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/cpu.py (original) +++ pypy/dist/pypy/lang/gameboy/cpu.py Sat May 24 15:05:34 2008 @@ -186,16 +186,20 @@ a = a.get() self.z_flag = ((a & 0xFF) == 0) - def c_flag_add(self, s, compare_and=0x01, reset=False): + def c_flag_compare(self, value, compare_and=0x01, reset=False): if reset: self.reset() - self.c_flag = ((s & compare_and) != 0) + print hex(value), hex(compare_and), (value & compare_and) != 0 + self.c_flag = ((value & compare_and) != 0) - def h_flag_compare(self, a, b): - self.h_flag = ((a & 0x0F) < (b & 0x0F)) + def h_flag_compare(self, value, a, inverted=False): + if inverted: + self.h_flag = ((value & 0x0F) < (a & 0x0F)) + else: + self.h_flag = ((value & 0x0F) > (a & 0x0F)) - def c_flag_compare(self, a, b): - self.c_flag = (a < b) + #def c_flag_compare(self, a, b): + # self.c_flag = (a < b) # # ------------------------------------------------------------------------------ @@ -385,18 +389,17 @@ def fetch_execute(self): # Execution opCode = self.fetch() - #print " fetch exe:", hex(opCode), " " - #, FETCH_EXECUTE_OP_CODES[opCode].__name__ + print " fetch exe:", hex(opCode), " ", FETCH_EXECUTE_OP_CODES[opCode].__name__ self.last_fetch_execute_op_code = opCode FETCH_EXECUTE_OP_CODES[opCode](self) def execute(self, opCode): self.instruction_counter += 1 - #print self.instruction_counter, "-"*60 - #print "exe: ", hex(opCode), " ", OP_CODES[opCode].__name__ - #print " pc:", hex(self.pc.get()), "sp:", hex(self.sp.get()) - #self.print_registers() + print self.instruction_counter, "-"*60 + print "exe: ", hex(opCode), " ", OP_CODES[opCode].__name__ + print " pc:", hex(self.pc.get()), "sp:", hex(self.sp.get()) + self.print_registers() self.last_op_code = opCode OP_CODES[opCode](self) @@ -499,9 +502,10 @@ def add_a(self, getCaller, setCaller=None): # ALU, 1 cycle added = (self.a.get() + getCaller.get()) & 0xFF - self.f.z_flag_compare(added, reset=True) - self.f.h_flag_compare(added, self.a.get()) - self.f.c_flag_compare(added, self.a.get()) + self.f.reset() + self.f.z_flag_compare(added) + self.f.h_flag_compare(added, self.a.get(), inverted=True) + self.f.c_flag = (added < self.a.get()) self.a.set(added) # 1 cycle def add_hl(self, register): @@ -554,7 +558,7 @@ def compare_a(self, getCaller, setCaller=None): # 1 cycle - self.compare_a_simple(int(self.a.get() - getCaller.get())) + self.compare_a_simple(self.a.get() - getCaller.get()) def compare_a_simple(self, s): s = s & 0xFF @@ -567,7 +571,8 @@ def hc_flag_finish(self, data): if data > self.a.get(): self.f.c_flag = True - self.f.h_flag_compare(self.a.get(), data) + #self.f.c_flag_compare(data, self.a.get()) + self.f.h_flag_compare(data, self.a.get()) def AND(self, getCaller, setCaller=None): # 1 cycle @@ -591,28 +596,20 @@ self.dec(doubleRegister.get, doubleRegister.set) def inc(self, getCaller, setCaller): - if getCaller.register == self.a: - self.add_a(NumberCallWrapper(1)) - else: - # 1 cycle - data = (getCaller.get() + 1) & 0xFF - self.dec_inc_flag_finish(data, setCaller, 0x00) + # 1 cycle + data = (getCaller.get() + 1) & 0xFF + self.dec_inc_flag_finish(data, setCaller, 0x00) def dec(self, getCaller, setCaller): - if setCaller.register == self.a: - self.subtract_a(NumberCallWrapper(1)) - else: - # 1 cycle - data = (getCaller.get() - 1) & 0xFF - self.dec_inc_flag_finish(data, setCaller, 0x0F) - self.f.n_flag = True + # 1 cycle + data = (getCaller.get() - 1) & 0xFF + self.dec_inc_flag_finish(data, setCaller, 0x0F) + self.f.n_flag = True def dec_inc_flag_finish(self, data, setCaller, compare): self.f.partial_reset(keep_c=True) self.f.z_flag_compare(data) - self.f.c_flag_compare(data, self.a.get()) - if (data & 0x0F) == compare: - self.f.h_flag = True + self.f.h_flag = ((data & 0x0F) == compare) setCaller.set(data) # 1 cycle def rotate_left_circular(self, getCaller, setCaller): @@ -681,8 +678,9 @@ def flags_and_setter_finish(self, s, setCaller, compare_and=0x01): # 2 cycles s &= 0xFF - self.f.z_flag_compare(s, reset=True) - self.f.c_flag_add(s, compare_and) + self.f.reset() + self.f.z_flag_compare(s) + self.f.c_flag_compare(s, compare_and) setCaller.set(s) # 1 cycle def swap(self, getCaller, setCaller): Modified: pypy/dist/pypy/lang/gameboy/gameboyImplementation.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/gameboyImplementation.py (original) +++ pypy/dist/pypy/lang/gameboy/gameboyImplementation.py Sat May 24 15:05:34 2008 @@ -73,10 +73,10 @@ def update_display(self): print " update_display" - #RSDL.LockSurface(self.screen) + RSDL.LockSurface(self.screen) self.draw_pixels() - #RSDL.UnlockSurface(self.screen) - #RSDL.Flip(self.screen) + RSDL.UnlockSurface(self.screen) + RSDL.Flip(self.screen) def draw_pixels(self): print "-"*60 Modified: pypy/dist/pypy/lang/gameboy/test/test_cpu.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/test/test_cpu.py (original) +++ pypy/dist/pypy/lang/gameboy/test/test_cpu.py Sat May 24 15:05:34 2008 @@ -350,7 +350,7 @@ opCode += 0x08 # ld_BC_nnnn to ld_SP_nnnn -def test_0x01_0x11_0x21_0x31(): +def test_0x01_0x11_0x21_0x31_load_register_nnnn(): cpu = get_cpu() registers= [cpu.bc, cpu.de, cpu.hl, cpu.sp] value = 0x12 @@ -544,10 +544,21 @@ cpu.dec(RegisterCallWrapper(a), RegisterCallWrapper(a)) assert_default_flags(cpu, z_flag=True, h_flag=False, n_flag=True, c_flag=True) + a.set(1) + cpu.f.c_flag = False + cpu.dec(RegisterCallWrapper(a), RegisterCallWrapper(a)) + assert_default_flags(cpu, z_flag=True, h_flag=False, n_flag=True, c_flag=False) + a.set(0x0F+1) + cpu.f.c_flag = True cpu.dec(RegisterCallWrapper(a), RegisterCallWrapper(a)) assert_default_flags(cpu, z_flag=False, h_flag=True, n_flag=True, c_flag=True) + a.set(0x0F+1) + cpu.f.c_flag = False + cpu.dec(RegisterCallWrapper(a), RegisterCallWrapper(a)) + assert_default_flags(cpu, z_flag=False, h_flag=True, n_flag=True, c_flag=False) + # dec_B C D E H L A def test_0x05_to_0x3D_dec_registers(): @@ -1090,14 +1101,14 @@ assert_default_flags(cpu, z_flag=False, n_flag=True) cpu.reset() - cpu.a.set(0xF0) + cpu.a.set(0xF0) cpu.b.set(0x01) cpu.compare_a(RegisterCallWrapper(cpu.b), None) assert_default_flags(cpu, z_flag=False, h_flag=True, n_flag=True) # cp_A_B to cp_A_A -def test_0xB8_to_0xBF(): +def test_0xB8_to_0xBF_compare_a(): cpu = get_cpu() opCode = 0xB8 value = 0x12 @@ -1113,13 +1124,13 @@ cycle_test(cpu, opCode, numCycles) if register == cpu.a: valueA = value - assert cpu.f.get() & constants.N_FLAG != 0 + assert cpu.f.n_flag == True if valueA == value: - assert cpu.f.get() & constants.Z_FLAG != 0 + assert cpu.f.z_flag == True if value < 0: - assert cpu.f.get() & constants.C_FLAG != 0 + assert cpu.f.c_flag == True if ((valueA-value) & 0x0F) > (valueA & 0x0F): - assert cpu.f.get() & constants.H_FLAG != 0 + assert cpu.f.h_flag == True value += 1 opCode += 0x01 @@ -1534,10 +1545,11 @@ assert_default_registers(cpu, pc=pc+1) -def test_rotateLeftCircular_flags(): +def test_rotateLeft_flags(): cpu = get_cpu() a = cpu.a a.set(0x01) + assert_default_flags(cpu) cpu.rotate_left_a() assert_default_flags(cpu, z_flag=False, c_flag=False) assert_default_registers(cpu, a=0x02, f=None) Modified: pypy/dist/pypy/lang/gameboy/test/test_memory_bank_controller.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/test/test_memory_bank_controller.py (original) +++ pypy/dist/pypy/lang/gameboy/test/test_memory_bank_controller.py Sat May 24 15:05:34 2008 @@ -1,7 +1,7 @@ from pypy.lang.gameboy.cartridge import * from pypy.lang.gameboy.timer import Clock -from pypy.lang.gameboy.constants import * +from pypy.lang.gameboy import constants import py def get_clock_driver(): @@ -10,13 +10,57 @@ RAM_SIZE = 3 ROM_SIZE = 2 -def get_ram(): - return [0] * RAM_SIZE * constants.RAM_BANK_SIZE - -def get_rom(): - return [0xFF] * ROM_SIZE * constants.ROM_BANK_SIZE +def get_ram(size=RAM_SIZE): + return [0] * size * constants.RAM_BANK_SIZE +def get_rom(size=ROM_SIZE): + return [0xFF] * size * constants.ROM_BANK_SIZE +def fail_ini_test(caller, ram_size, rom_size): + try: + caller(ram_size, rom_size) + py.test.fail("invalid ram/rom bounds check") + except: + pass + + + +def read_write_test(mbc, lower, upper): + write_bounds_test(mbc, lower, upper) + read_bounds_test(mbc, lower, upper) + +def write_bounds_test(mbc, lower, upper): + value = 0 + try: + mbc.write(lower-1, value) + py.test.fail("lower bound check failed") + except: + pass + for address in range(lower, upper): + mbc.write(address, value % 0xFF) + value += 1 + try: + mbc.write(upper+1, value) + py.test.fail("lower upper check failed") + except: + pass + +def read_bounds_test(mbc, lower, upper): + value = 0 + try: + mbc.read(lower-1) + py.test.fail("lower bound check failed") + except: + pass + for address in range(lower, upper): + assert mbc.read(address) != None + try: + mbc.read(upper+1) + py.test.fail("lower upper check failed") + except: + pass + +# ----------------------------------------------------------------------------- def test_mbc_init(): try: MBC(get_ram(), get_rom(), get_clock_driver()) @@ -95,9 +139,12 @@ def get_default_mbc(): return DefaultMBC([0]*0xFFFF, [0]*0xFFFF, get_clock_driver()) -def test_default_mbc_read(): - py.test.skip("not yet implemented") +def test_default_mbc_read_write(): + py.test.skip("buggy implementation of DefaultMBC") mbc = get_default_mbc() + for i in range(0xFFFF): + mbc.write(i, i) + assert mbc.read(i) == i def test_default_mbc_write(): py.test.skip("not yet implemented") @@ -105,9 +152,46 @@ # ----------------------------------------------------------------------------- -def get_mbc1(): - return MBC1([0]*0x5FFF,[0]*0xBFFF, get_clock_driver()) +def get_mbc1(rom_size=128, ram_size=4): + return MBC1(get_rom(rom_size), get_ram(ram_size), get_clock_driver()) +def test_mbc1_create(): + mbc1 = get_mbc1() + assert mbc1.rom_bank == constants.ROM_BANK_SIZE + assert mbc1.memory_model == 0 + assert mbc1.ram_enable == False + assert mbc1.ram_bank == 0 + fail_ini_test(get_mbc1, 128, 5) + fail_ini_test(get_mbc1, 128, -1) + fail_ini_test(get_mbc1, 1, 4) + fail_ini_test(get_mbc1, 129, 4) + +def test_mbc1_read_write(): + mbc = get_mbc1() + read_write_test(mbc, 0, 0x7FFF) + value = 0 + for address in range(0x1FFF+1): + mbc.write(address, 0x0A) + assert mbc.ram_enable == True + mbc.write(address, 0x00) + assert mbc.ram_enable == False + + import pdb + value = 1 + for address in range(0x2000, 0x3FFF): + mbc.memory_model = 0 + rom_bank = mbc.rom_bank + #pdb.runcall(mbc.write, address, value) + mbc.write(address, value) + assert mbc.rom_bank == ((rom_bank & 0x180000) + \ + ((value & 0x1F) << 14)) & mbc.rom_size + mbc.memory_model = 10 + mbc.write(address, value) + assert mbc.rom_bank == ((value & 0x1F) << 14) & mbc.rom_size + value = (value+1) % (0x1F-1) +1 + + + def test_mbc1_write(): py.test.skip("buggy implementation of MBC1++") mbc1 = get_mbc1() @@ -121,9 +205,17 @@ # ----------------------------------------------------------------------------- -def get_mbc2(): - return MBC2([0]*0x5FFF,[0]*0xBFFF, get_clock_driver()) +def get_mbc2(rom_size=16, ram_size=1): + return MBC2(get_rom(rom_size), get_ram(ram_size), get_clock_driver()) +def test_mbc2_create(): + get_mbc2() + fail_ini_test(get_mbc2, 2, 0) + fail_ini_test(get_mbc2, 2, 2) + fail_ini_test(get_mbc2, 1, 1) + fail_ini_test(get_mbc2, 17, 1) + + def test_mbc2_read_write(): py.test.skip("not yet implemented") mbc2 = get_mbc2() @@ -135,9 +227,16 @@ # ----------------------------------------------------------------------------- -def get_mbc3(): - return MBC3([0]*0x5FFF,[0]*0xBFFF, get_clock_driver()) +def get_mbc3(rom_size=128, ram_size=4): + return MBC3(get_rom(rom_size), get_ram(ram_size), get_clock_driver()) +def test_mbc3_create(): + get_mbc3() + fail_ini_test(get_mbc3, 128, -1) + fail_ini_test(get_mbc3, 128, 5) + fail_ini_test(get_mbc3, 1, 4) + fail_ini_test(get_mbc3, 129, 4) + def test_mbc3_read(): py.test.skip("not yet implemented") mbc3 = get_mbc3() @@ -148,8 +247,15 @@ # ----------------------------------------------------------------------------- -def get_mbc5(): - return MBC5([0]*0x5FFF,[0]*0xBFFF, get_clock_driver()) +def get_mbc5(rom_size=512, ram_size=16): + return MBC5(get_rom(rom_size), get_ram(ram_size), get_clock_driver()) + +def test_mbc5_create(): + get_mbc5() + fail_ini_test(get_mbc5, 512, -1) + fail_ini_test(get_mbc5, 512, 17) + fail_ini_test(get_mbc5, 1, 16) + fail_ini_test(get_mbc5, 513, 16) def test_mbc5_read(): py.test.skip("not yet implemented") @@ -161,8 +267,15 @@ # ----------------------------------------------------------------------------- -def get_huc1(): - return HuC1([0]*0x5FFF,[0]*0xBFFF, get_clock_driver()) +def get_huc1(rom_size=128, ram_size=4): + return HuC1(get_rom(rom_size), get_ram(ram_size), get_clock_driver()) + +def test_huc1_create(): + get_huc1() + fail_ini_test(get_huc1, 128, 5) + fail_ini_test(get_huc1, 128, -1) + fail_ini_test(get_huc1, 1, 4) + fail_ini_test(get_huc1, 129, 4) def test_huc1_read(): py.test.skip("not yet implemented") @@ -174,8 +287,15 @@ # ----------------------------------------------------------------------------- -def get_huc3(): - return HuC3([0]*0x5FFF,[0]*0xBFFF, get_clock_driver()) +def get_huc3(rom_size=128, ram_size=4): + return HuC3(get_rom(rom_size), get_ram(ram_size), get_clock_driver()) + +def test_huc1_create(): + get_huc3() + fail_ini_test(get_huc3, 128, 5) + fail_ini_test(get_huc3, 128, -1) + fail_ini_test(get_huc3, 1, 4) + fail_ini_test(get_huc3, 129, 4) def test_huc3_read(): py.test.skip("not yet implemented") Modified: pypy/dist/pypy/lang/gameboy/test/test_rom.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/test/test_rom.py (original) +++ pypy/dist/pypy/lang/gameboy/test/test_rom.py Sat May 24 15:05:34 2008 @@ -34,6 +34,7 @@ py.test.skip() gameboy = GameBoy() gameboy.load_cartridge_file(ROM_PATH+"/rom1/rom1.raw", verify=False) + cpu = gameboy.cpu emulate_step_op_codes_test(gameboy, []) # ------------------------------------------------------------------------------ @@ -53,12 +54,14 @@ gameboy = GameBoy() gameboy.load_cartridge_file(ROM_PATH+"/rom3/rom3.gb") gameboy.emulate(EMULATION_CYCLES) + cpu = gameboy.cpu def test_rom3_step(): py.test.skip() gameboy = GameBoy() gameboy.load_cartridge_file(ROM_PATH+"/rom3/rom3.gb") + cpu = gameboy.cpu # jp nop emulate_step_op_codes_test(gameboy, [0xC3]) emulate_step_op_codes_test(gameboy, [0]*12) @@ -70,16 +73,18 @@ gameboy = GameBoy() gameboy.load_cartridge_file(ROM_PATH+"/rom4/rom4.gb") gameboy.emulate(EMULATION_CYCLES) - - assert gameboy.cpu.ime == False - assert gameboy.cpu.halted == True - assert gameboy.cpu.a.get() != 0xFF + cpu = gameboy.cpu + assert cpu.ime == False + assert cpu.halted == True + assert cpu.a.get() != 0xFF def test_rom4_step(): gameboy = GameBoy() gameboy.load_cartridge_file(ROM_PATH+"/rom4/rom4.gb") + cpu = gameboy.cpu + emulate_step_op_codes_test(gameboy, [0, 0xC3, 0xF3, 0x21]) - assert gameboy.cpu.hl.get() == 0xFF40 + assert cpu.hl.get() == 0xFF40 emulate_step_op_codes_test(gameboy, [0xCB, 0x76, 0x76, 0x3E]) @@ -89,41 +94,50 @@ gameboy = GameBoy() gameboy.load_cartridge_file(ROM_PATH+"/rom5/rom5.gb") gameboy.emulate(EMULATION_CYCLES) + cpu = gameboy.cpu # stop test - assert gameboy.cpu.a.get() != 0xFF + assert cpu.a.get() != 0xFF def test_rom5_step(): + py.test.skip("dec and inc dont work as excepted") gameboy = GameBoy() gameboy.load_cartridge_file(ROM_PATH+"/rom5/rom5.gb") - + cpu = gameboy.cpu + # intro and start of .loop1 emulate_step_op_codes_test(gameboy, [0, 0xC3, 0xF3, 0xAF, 0x3D, 0xC2]) - assert gameboy.cpu.pc.get() == 0x0152 - assert gameboy.cpu.a.get() == 0xFF + assert cpu.pc.get() == 0x0152 + assert cpu.a.get() == 0xFF + # looping .loop1 emulate_step_op_codes_test(gameboy, [0x3D, 0xC2]*0xFF) - assert gameboy.cpu.a.get() == 0 - + assert cpu.a.get() == 0 + # debug, start .loop2 emulate_step_op_codes_test(gameboy, [0xDD, 0xAF, 0xC6]) - pc = gameboy.cpu.pc.get() - assert gameboy.cpu.a.get() == 1 - assert gameboy.cpu.f.c_flag == False + pc = cpu.pc.get() + assert cpu.a.get() == 1 + assert cpu.f.c_flag == False + # check jr in .loop2 emulate_step_op_codes_test(gameboy, [0x30]) - assert gameboy.cpu.pc.get() == pc-2 + assert cpu.pc.get() == pc-2 + # looping in .loop2 emulate_step_op_codes_test(gameboy, [0xC6, 0x30]*255) - assert gameboy.cpu.a.get() == 0 - assert gameboy.cpu.f.c_flag == True - + assert cpu.a.get() == 0 + assert cpu.f.c_flag == True + # debugg call reseting emulate_step_op_codes_test(gameboy, [0xDD, 0xAF]) - assert gameboy.cpu.a.get() == 0 - assert gameboy.cpu.f.c_flag == False - pc = gameboy.cpu.pc.get() + assert cpu.a.get() == 0 + assert cpu.f.c_flag == False + pc = cpu.pc.get() + # enter .loop3 + c_flag = cpu.f.c_flag emulate_step_op_codes_test(gameboy, [0x3C, 0xD2]) - assert gameboy.cpu.f.c_flag == False - assert gameboy.cpu.a.get() == 1 - assert gameboy.cpu.pc.get() == pc + assert cpu.f.c_flag == c_flag + assert cpu.a.get() == 1 + assert cpu.pc.get() == pc + # looping in .loop3 emulate_step_op_codes_test(gameboy, [0x3C, 0xD2]*255) - assert gameboy.cpu.a.get() == 0 - assert gameboy.cpu.f.c_flag == True + assert cpu.a.get() == 0 + assert cpu.f.c_flag == False emulate_step_op_codes_test(gameboy, [0xDD, 0x76, 0x76]) @@ -227,6 +241,7 @@ gameboy = GameBoy() gameboy.load_cartridge_file(ROM_PATH+"/rom7/rom7.gb") gameboy.emulate(EMULATION_CYCLES) + cpu = gameboy.cpu def test_rom7_step(): @@ -238,7 +253,7 @@ gameboy = GameBoy() gameboy.load_cartridge_file(ROM_PATH+"/rom8/rom8.gb") gameboy.emulate(EMULATION_CYCLES) - + cpu = gameboy.cpu # ------------------------------------------------------------------------------ @@ -247,4 +262,5 @@ gameboy = GameBoy() gameboy.load_cartridge_file(ROM_PATH+"/rom9/rom9.gb") gameboy.emulate(EMULATION_CYCLES) + cpu = gameboy.cpu From cami at codespeak.net Sat May 24 16:17:16 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Sat, 24 May 2008 16:17:16 +0200 (CEST) Subject: [pypy-svn] r55192 - in pypy/dist/pypy/lang/gameboy: . test Message-ID: <20080524141716.CDA372A805D@codespeak.net> Author: cami Date: Sat May 24 16:17:14 2008 New Revision: 55192 Modified: pypy/dist/pypy/lang/gameboy/cartridge.py pypy/dist/pypy/lang/gameboy/test/test_memory_bank_controller.py Log: added more memory bank controller tests Modified: pypy/dist/pypy/lang/gameboy/cartridge.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/cartridge.py (original) +++ pypy/dist/pypy/lang/gameboy/cartridge.py Sat May 24 16:17:14 2008 @@ -286,9 +286,12 @@ return self.rom[address] & 0xFF elif address <= 0x7FFF:# 4000-7FFF return self.rom[self.rom_bank + (address & 0x3FFF)] & 0xFF - elif address >= 0xA000 and address <= 0xBFFF and self.ram_enable: # A000-BFFF - return self.ram[self.ram_bank + (address & 0x1FFF)] & 0xFF - raise Exception("MBC: Invalid address, out of range") + elif address >= 0xA000 and address <= 0xBFFF: # A000-BFFF + if self.ram_enable: + return self.ram[self.ram_bank + (address & 0x1FFF)] & 0xFF + else: + raise Exception("RAM is not Enabled") + raise Exception("MBC: Invalid address, out of range: %s" % hex(address)) def write(self, address, data): raise Exception("MBC: Invalid write access") @@ -346,7 +349,7 @@ elif address >= 0xA000 and address <= 0xBFFF and self.ram_enable: # A000-BFFF self.ram[self.ram_bank + (address & 0x1FFF)] = data else: - raise Exception("Invalid memory Access") + raise Exception("Invalid memory Access address: %s" % hex(address)) def write_ram_enable(self, address, data): if self.ram_size > 0: @@ -390,10 +393,17 @@ min_rom_bank_size=2, max_rom_bank_size=16) - + def read(self, address): if address > 0xA1FF: - return 0xFF + raise Exception("MBC2 out of Bounds: %s" % hex(address)) + elif address >= 0xA000: + return self.ram[address & 0x01FF] + elif address >= 0xA000 and address <= 0xA1FF: # A000-BFFF + if self.ram_enable: + return self.ram[self.ram_bank + (address & 0x1FFF)] & 0xFF + else: + raise Exception("RAM is not Enabled") else: return MBC.read(self, address) @@ -444,20 +454,20 @@ def reset(self): MBC.reset(self) - self.clockLDaysclockLControl = None + self.clock_latched_daysclock_latched_control = None self.clock_time = self.clock.get_time() self.clock_latch = 0 self.clock_register = 0 - self.clockSeconds = 0 - self.clockMinutes = 0 - self.clockHours = 0 - self.clockDays = 0 - self.clockControl = 0 - self.clockLSeconds = 0 - self.clockLMinutes = 0 - self.clockLHours = 0 - self.clockLDays = 0 - self.clockLControl = 0 + self.clock_seconds = 0 + self.clock_minutes = 0 + self.clock_hours = 0 + self.clock_days = 0 + self.clock_control = 0 + self.clock_latched_seconds = 0 + self.clock_latched_minutes = 0 + self.clock_latched_hours = 0 + self.clock_latched_days = 0 + self.clock_latched_control = 0 def read(self, address): @@ -471,15 +481,15 @@ def read_clock_data(self, address): if self.clock_register == 0x08: - return self.clockLSeconds + return self.clock_latched_seconds if self.clock_register == 0x09: - return self.clockLMinutes + return self.clock_latched_minutes if self.clock_register == 0x0A: - return self.clockLHours + return self.clock_latched_hours if self.clock_register == 0x0B: - return self.clockLDays + return self.clock_latched_days if self.clock_register == 0x0C: - return self.clockLControl + return self.clock_latched_control raise Exception("MBC*.read_clock_data invalid address %i") def write(self, address, data): @@ -522,52 +532,52 @@ else: self.update_clock() if self.clock_register == 0x08: - self.clockSeconds = data + self.clock_seconds = data if self.clock_register == 0x09: - self.clockMinutes = data + self.clock_minutes = data if self.clock_register == 0x0A: - self.clockHours = data + self.clock_hours = data if self.clock_register == 0x0B: - self.clockDays = data + self.clock_days = data if self.clock_register == 0x0C: - self.clockControl = (self.clockControl & 0x80) | data + self.clock_control = (self.clock_control & 0x80) | data def latch_clock(self): self.update_clock() - self.clockLSeconds = self.clockSeconds - self.clockLMinutes = self.clockMinutes - self.clockLHours = self.clockHours - self.clockLDays = self.clockDays & 0xFF - self.clockLControl = (self.clockControl & 0xFE) | ((self.clockDays >> 8) & 0x01) + self.clock_latched_seconds = self.clock_seconds + self.clock_latched_minutes = self.clock_minutes + self.clock_latched_hours = self.clock_hours + self.clock_latched_days = self.clock_days & 0xFF + self.clock_latched_control = (self.clock_control & 0xFE) | ((self.clock_days >> 8) & 0x01) def update_clock(self): now = self.clock.get_time() - if (self.clockControl & 0x40) == 0: + if (self.clock_control & 0x40) == 0: elapsed = now - self.clock_time while elapsed >= 246060: elapsed -= 246060 - self.clockDays+=1 + self.clock_days+=1 while elapsed >= 6060: elapsed -= 6060 - self.clockHours+=1 + self.clock_hours+=1 while elapsed >= 60: elapsed -= 60 - self.clockMinutes+=1 - self.clockSeconds += elapsed - while self.clockSeconds >= 60: - self.clockSeconds -= 60 - self.clockMinutes+=1 - while self.clockMinutes >= 60: - self.clockMinutes -= 60 - self.clockHours+=1 - while self.clockHours >= 24: - self.clockHours -= 24 - self.clockDays+=1 - while self.clockDays >= 512: - self.clockDays -= 512 - self.clockControl |= 0x80 + self.clock_minutes+=1 + self.clock_seconds += elapsed + while self.clock_seconds >= 60: + self.clock_seconds -= 60 + self.clock_minutes+=1 + while self.clock_minutes >= 60: + self.clock_minutes -= 60 + self.clock_hours+=1 + while self.clock_hours >= 24: + self.clock_hours -= 24 + self.clock_days+=1 + while self.clock_days >= 512: + self.clock_days -= 512 + self.clock_control |= 0x80 self.clock_time = now Modified: pypy/dist/pypy/lang/gameboy/test/test_memory_bank_controller.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/test/test_memory_bank_controller.py (original) +++ pypy/dist/pypy/lang/gameboy/test/test_memory_bank_controller.py Sat May 24 16:17:14 2008 @@ -3,6 +3,7 @@ from pypy.lang.gameboy.timer import Clock from pypy.lang.gameboy import constants import py +import pdb def get_clock_driver(): return Clock() @@ -25,7 +26,7 @@ -def read_write_test(mbc, lower, upper): +def basic_read_write_test(mbc, lower, upper): write_bounds_test(mbc, lower, upper) read_bounds_test(mbc, lower, upper) @@ -52,15 +53,25 @@ py.test.fail("lower bound check failed") except: pass - for address in range(lower, upper): - assert mbc.read(address) != None + for address in range(lower, upper, 1): + assert mbc.read(address) != None try: mbc.read(upper+1) py.test.fail("lower upper check failed") except: pass +def write_ram_enable_test(mbc): + value = 0 + for address in range(0x1FFF+1): + mbc.write(address, 0x0A) + assert mbc.ram_enable == True + mbc.write(address, 0x00) + assert mbc.ram_enable == False + + # ----------------------------------------------------------------------------- + def test_mbc_init(): try: MBC(get_ram(), get_rom(), get_clock_driver()) @@ -112,7 +123,7 @@ except: pass -def test_mbc_read_write_test(mbc=None): +def test_mbc_basic_read_write_test(mbc=None): if mbc==None: mbc = MBC([0]*0xFFFF,[0]*0xFFFF, get_clock_driver(),1, 0xFFFF, 2, 0xFFFF) @@ -155,7 +166,7 @@ def get_mbc1(rom_size=128, ram_size=4): return MBC1(get_rom(rom_size), get_ram(ram_size), get_clock_driver()) -def test_mbc1_create(): +def test_mbc1(): mbc1 = get_mbc1() assert mbc1.rom_bank == constants.ROM_BANK_SIZE assert mbc1.memory_model == 0 @@ -166,42 +177,60 @@ fail_ini_test(get_mbc1, 1, 4) fail_ini_test(get_mbc1, 129, 4) -def test_mbc1_read_write(): - mbc = get_mbc1() - read_write_test(mbc, 0, 0x7FFF) - value = 0 - for address in range(0x1FFF+1): - mbc.write(address, 0x0A) - assert mbc.ram_enable == True - mbc.write(address, 0x00) - assert mbc.ram_enable == False + basic_read_write_test(mbc1, 0, 0x7FFF) - import pdb +def test_mbc1_write_ram_enable(): + write_ram_enable_test(get_mbc1()) + +def test_mbc_write_rom_bank_test1(): + mbc= get_mbc1() value = 1 - for address in range(0x2000, 0x3FFF): + for address in range(0x2000, 0x3FFF+1): mbc.memory_model = 0 rom_bank = mbc.rom_bank - #pdb.runcall(mbc.write, address, value) mbc.write(address, value) assert mbc.rom_bank == ((rom_bank & 0x180000) + \ ((value & 0x1F) << 14)) & mbc.rom_size mbc.memory_model = 10 mbc.write(address, value) assert mbc.rom_bank == ((value & 0x1F) << 14) & mbc.rom_size - value = (value+1) % (0x1F-1) +1 + value = (value+1) % (0x1F-1) +1 +def test_mbc1_write_rom_bank_test2(): + mbc = get_mbc1() + value = 1 + for address in range(0x4000, 0x5FFF+1): + mbc.memory_model = 0 + rom_bank = mbc.rom_bank + mbc.write(address, value) + assert mbc.rom_bank == ((mbc.rom_bank & 0x07FFFF) + \ + ((value & 0x03) << 19)) & mbc.rom_size; + mbc.memory_model = 10 + mbc.write(address, value) + assert mbc.ram_bank == ((value & 0x03) << 13) & mbc.ram_size + value += 1 + value %= 0xFF +def test_mbc1_read_memory_model(): + mbc = get_mbc1() + value = 1 + for address in range(0x6000, 0x7FFF+1): + mbc.write(address, value) + assert mbc.memory_model == (value & 0x01) + value += 1 + value %= 0xFF -def test_mbc1_write(): - py.test.skip("buggy implementation of MBC1++") - mbc1 = get_mbc1() - test_mbc_read_write_test(mbc1) - -def test_mbc1_read(): - py.test.skip("not yet implemented") - mbc1 = get_mbc1() - # the same as in mbc - pass +def test_mbc1_read_write_ram(): + mbc = get_mbc1() + value = 1 + mbc.ram_enable = True + for address in range(0xA000, 0xBFFF+1): + mbc.write(address, value) + #pdb.runcall(mbc.write, address, value) + assert mbc.ram[mbc.ram_bank + (address & 0x1FFF)] == value + assert mbc.read(address) == value; + value += 1 + value %= 0xFF # ----------------------------------------------------------------------------- @@ -209,41 +238,160 @@ return MBC2(get_rom(rom_size), get_ram(ram_size), get_clock_driver()) def test_mbc2_create(): - get_mbc2() - fail_ini_test(get_mbc2, 2, 0) - fail_ini_test(get_mbc2, 2, 2) - fail_ini_test(get_mbc2, 1, 1) - fail_ini_test(get_mbc2, 17, 1) - - -def test_mbc2_read_write(): - py.test.skip("not yet implemented") mbc2 = get_mbc2() + fail_ini_test(mbc2, 2, 0) + fail_ini_test(mbc2, 2, 2) + fail_ini_test(mbc2, 1, 1) + fail_ini_test(mbc2, 17, 1) + # only to the upper border of mbc + basic_read_write_test(mbc2, 0, 0x7FFF) - -def test_mbc2_write(): - py.test.skip("not yet implemented") - mbc2 = get_mbc2() + +def test_mbc2_write_ram_enable(): + mbc = get_mbc2() + value = 0 + for address in range(0x1FFF+1): + mbc.ram_enable = -1 + mbc.write(address, 0x0A) + if (address & 0x0100) == 0: + assert mbc.ram_enable == True + mbc.write(address, 0x00) + assert mbc.ram_enable == False + else: + assert mbc.ram_enable == -1 + +def test_mbc2_write_rom_bank_test1(): + mbc = get_mbc2() + value = 1 + for address in range(0x2000, 0x3FFF+1): + mbc.rom_bank = -1 + mbc.write(address, value) + if (address & 0x0100) != 0: + assert mbc.rom_bank == ((value & 0x0F) << 14) & mbc.rom_size + else: + assert mbc.rom_bank == -1 + value = (value + 1) % (0x0F-1) + 1 + +def test_mbc2_read_write_ram(): + mbc = get_mbc2() + value = 1 + mbc.ram_enable = True + for address in range(0xA000, 0xA1FF+1): + mbc.write(address, value) + assert mbc.ram[(address & 0x01FF)] == value & 0x0F + assert mbc.read(address) == value; + value += 1 + value %= 0x0F # ----------------------------------------------------------------------------- - + def get_mbc3(rom_size=128, ram_size=4): return MBC3(get_rom(rom_size), get_ram(ram_size), get_clock_driver()) def test_mbc3_create(): - get_mbc3() - fail_ini_test(get_mbc3, 128, -1) - fail_ini_test(get_mbc3, 128, 5) - fail_ini_test(get_mbc3, 1, 4) - fail_ini_test(get_mbc3, 129, 4) - -def test_mbc3_read(): - py.test.skip("not yet implemented") mbc3 = get_mbc3() + fail_ini_test(mbc3, 128, -1) + fail_ini_test(mbc3, 128, 5) + fail_ini_test(mbc3, 1, 4) + fail_ini_test(mbc3, 129, 4) + basic_read_write_test(mbc3, 0, 0x7FFF) + +def test_mbc3_write_ram_enable(): + write_ram_enable_test(get_mbc3()) + +def test_mbc3_write_rom_bank(): + mbc= get_mbc3() + value = 1 + for address in range(0x2000, 0x3FFF+1): + mbc.memory_model = 0 + rom_bank = mbc.rom_bank + mbc.write(address, value) + if value == 0: + assert mbc.rom_bank == ((1 & 0x7F) << 14) & mbc.rom_size + else: + assert mbc.rom_bank == ((value & 0x7F) << 14) & mbc.rom_size + value += 1 + value %= 0xFF + +def test_mbc3_write_ram_bank(): + mbc = get_mbc3() + value = 1 + for address in range(0x4000, 0x5FFF+1): + mbc.memory_model = 0 + mbc.write(address, value) + if value >= 0 and value <= 0x03: + assert mbc.ram_bank == (value << 13) & mbc.ram_size + else: + assert mbc.ram_bank == -1; + assert mbc.clock_register == value + value += 1 + value %= 0xFF + +def test_mbc3_write_clock_latch(): + mbc = get_mbc3() + value = 1 + for address in range(0x6000, 0x7FFF+1): + mbc.write(address, value) + if value == 0 or value == 1: + assert mbc.clock_latch == value + if value == 1: + # clock update check... + pass + value += 1 + value %= 0xFF + +def test_mbc3_read_write_ram(): + mbc = get_mbc3() + value = 1 + mbc.ram_enable = True + for address in range(0xA000, 0xBFFF+1): + mbc.write(address, value) + #pdb.runcall(mbc.write, address, value) + assert mbc.ram[mbc.ram_bank + (address & 0x1FFF)] == value + assert mbc.read(address) == value; + value += 1 + value %= 0xFF + +def test_mbc3_read_write_clock(): + mbc = get_mbc3() + value = 1 + mbc.ram_enable = True + mbc.ram_bank = -1 + old_clock_value = -2 + for address in range(0xA000, 0xBFFF+1): + mbc.clock_register = 0x08 + mbc.write(address, value) + assert mbc.clock_seconds == value + + mbc.clock_register = 0x09 + mbc.write(address, value) + assert mbc.clock_minutes == value + + mbc.clock_register = 0x0A + mbc.write(address, value) + assert mbc.clock_hours == value + + mbc.clock_register = 0x0B + mbc.write(address, value) + assert mbc.clock_days == value + + mbc.clock_register = 0x0C + clock_control = mbc.clock_control + mbc.write(address, value) + assert mbc.clock_control == ((clock_control & 0x80) | value) + + value += 1 + value %= 0xFF -def test_mbc3_write(): +def test_mbc3_update_clock(): py.test.skip("not yet implemented") - mbc3 = get_mbc3() + mbc = get_mbc3() + + +def test_mbc3_latch_clock(): + py.test.skip("not yet implemented") + mbc = get_mbc3() + # ----------------------------------------------------------------------------- From cfbolz at codespeak.net Sat May 24 19:13:20 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sat, 24 May 2008 19:13:20 +0200 (CEST) Subject: [pypy-svn] r55193 - in pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk: . test Message-ID: <20080524171320.4EBDA49813C@codespeak.net> Author: cfbolz Date: Sat May 24 19:13:17 2008 New Revision: 55193 Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_model.py Log: reverting r55142, it doesn't make much sense and breaks translation Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py Sat May 24 19:13:17 2008 @@ -403,11 +403,11 @@ def at0(self, index0): from pypy.lang.smalltalk import utility - return self.getword(index0) + return utility.wrap_int(self.getword(index0)) def atput0(self, index0, w_value): from pypy.lang.smalltalk import utility - self.setword(index0, w_value) + self.setword(index0, utility.unwrap_int(w_value)) def getword(self, n): return self.words[n] Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_model.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_model.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_model.py Sat May 24 19:13:17 2008 @@ -196,12 +196,3 @@ assert res assert w_clsa.as_class_get_shadow() is s_clsb assert w_clsb.as_class_get_shadow() is s_clsa - -def test_wordsobject_at0_atput0(): - w_words = model.W_WordsObject(None, 3) - w_words.atput0(0, 'a') - w_words.atput0(1, 'b') - w_words.atput0(2, 'c') - assert w_words.at0(0) == 'a' - assert w_words.at0(1) == 'b' - assert w_words.at0(2) == 'c' From afa at codespeak.net Sat May 24 22:25:57 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Sat, 24 May 2008 22:25:57 +0200 (CEST) Subject: [pypy-svn] r55194 - in pypy/dist/pypy/translator: . test Message-ID: <20080524202557.B1B7E2A01AC@codespeak.net> Author: afa Date: Sat May 24 22:25:56 2008 New Revision: 55194 Modified: pypy/dist/pypy/translator/geninterplevel.py pypy/dist/pypy/translator/test/snippet.py Log: Classmethods crash the geninterp transformer. Skip them, until someone really need them. Modified: pypy/dist/pypy/translator/geninterplevel.py ============================================================================== --- pypy/dist/pypy/translator/geninterplevel.py (original) +++ pypy/dist/pypy/translator/geninterplevel.py Sat May 24 22:25:56 2008 @@ -51,7 +51,7 @@ from pypy.objspace.flow.model import Variable, Constant, SpaceOperation from pypy.objspace.flow.model import c_last_exception, checkgraph from pypy.interpreter.pycode import CO_VARARGS, CO_VARKEYWORDS -from types import FunctionType, CodeType, ModuleType +from types import FunctionType, CodeType, ModuleType, MethodType from pypy.interpreter.error import OperationError from pypy.interpreter.argument import Arguments from pypy.translator.backendopt.ssa import SSI_to_SSA @@ -802,6 +802,9 @@ ## if isinstance(value, FunctionType) and value not in self.translator.flowgraphs and self.translator.frozen: ## log.WARNING("skipped function: %s" % value) ## continue + if isinstance(value, MethodType) and value.im_self is cls: + log.WARNING("skipped classmethod: %s" % value) + continue yield 'space.setattr(%s, %s, %s)' % ( name, self.nameof(key), self.nameof(value)) Modified: pypy/dist/pypy/translator/test/snippet.py ============================================================================== --- pypy/dist/pypy/translator/test/snippet.py (original) +++ pypy/dist/pypy/translator/test/snippet.py Sat May 24 22:25:56 2008 @@ -473,6 +473,15 @@ call_Z_my_method(global_z) call_Z_my_method(z) +class ClassWithMethods: + def cm(cls, x): + return x + cm = classmethod(cm) + + def sm(x): + return x + sm = staticmethod(sm) + global_c = C() global_c.a = 1 From afa at codespeak.net Sat May 24 22:37:23 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Sat, 24 May 2008 22:37:23 +0200 (CEST) Subject: [pypy-svn] r55195 - in pypy/dist/pypy/translator/goal: . test2 Message-ID: <20080524203723.3CB2C2A01AC@codespeak.net> Author: afa Date: Sat May 24 22:37:22 2008 New Revision: 55195 Modified: pypy/dist/pypy/translator/goal/nanos.py pypy/dist/pypy/translator/goal/test2/test_nanos.py Log: The os functions used by the nanos module are all RPython, after all. Remove the NOT_RPYTHON marks, which I think generates better code. (i.e translated code vs. python bytecode) Note: This won't work on windows if CPython is older than 2.4.4, because ntpath.abspath used to modify itself(!) see http://svn.python.org/view?rev=45632&view=rev Modified: pypy/dist/pypy/translator/goal/nanos.py ============================================================================== --- pypy/dist/pypy/translator/goal/nanos.py (original) +++ pypy/dist/pypy/translator/goal/nanos.py Sat May 24 22:37:22 2008 @@ -33,21 +33,11 @@ ''', filename=__file__) app_os = applevel(r''' - # NOT_RPYTHON - import sys - sysmodules = sys.modules.keys() - from os import sep, pathsep, getenv, name, fdopen try: from os import readlink except ImportError: pass - - # restore the previous list of loaded modules - for name in sys.modules.keys(): - if name not in sysmodules: - del sys.modules[name] - del sys ''', filename=__file__) def getenv(space, w_name): Modified: pypy/dist/pypy/translator/goal/test2/test_nanos.py ============================================================================== --- pypy/dist/pypy/translator/goal/test2/test_nanos.py (original) +++ pypy/dist/pypy/translator/goal/test2/test_nanos.py Sat May 24 22:37:22 2008 @@ -22,5 +22,9 @@ assert not space.is_true( space.call_method(space.sys.get('modules'), '__contains__', space.wrap('os'))) - + # But that 'sys' is still present + assert space.is_true( + space.call_method(space.sys.get('modules'), + '__contains__', space.wrap('sys'))) + entry_point(['', '-c', 'print 42']) From xoraxax at codespeak.net Sat May 24 23:50:54 2008 From: xoraxax at codespeak.net (xoraxax at codespeak.net) Date: Sat, 24 May 2008 23:50:54 +0200 (CEST) Subject: [pypy-svn] r55196 - in pypy/dist/pypy/module: __builtin__ sys Message-ID: <20080524215054.3CDE1169EDC@codespeak.net> Author: xoraxax Date: Sat May 24 23:50:50 2008 New Revision: 55196 Removed: pypy/dist/pypy/module/__builtin__/app_help.py Modified: pypy/dist/pypy/module/__builtin__/__init__.py pypy/dist/pypy/module/sys/app.py Log: Merged CPython's copyright string into PyPy's (mainly because PyPy is using their stdlib etc.), removed the duplicated code in app_help. Note that site.py is implementing those names. Modified: pypy/dist/pypy/module/__builtin__/__init__.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/__init__.py (original) +++ pypy/dist/pypy/module/__builtin__/__init__.py Sat May 24 23:50:50 2008 @@ -23,12 +23,6 @@ expose__file__attribute = False appleveldefs = { - 'quit' : 'app_help.exit', - 'exit' : 'app_help.exit', - 'copyright' : 'app_help.copyright', - 'license' : 'app_help.license', - 'help' : 'app_help.help', - 'execfile' : 'app_io.execfile', 'raw_input' : 'app_io.raw_input', 'input' : 'app_io.input', Modified: pypy/dist/pypy/module/sys/app.py ============================================================================== --- pypy/dist/pypy/module/sys/app.py (original) +++ pypy/dist/pypy/module/sys/app.py Sat May 24 23:50:50 2008 @@ -46,6 +46,16 @@ Copyright 2003-2008 PyPy development team. All rights reserved. For further information see http://www.codespeak.net/pypy. -Some materials may have a different copyright. -In these cases, this is explicitly noted in the source code file. + +Portions Copyright (c) 2001-2008 Python Software Foundation. +All Rights Reserved. + +Portions Copyright (c) 2000 BeOpen.com. +All Rights Reserved. + +Portions Copyright (c) 1995-2001 Corporation for National Research Initiatives. +All Rights Reserved. + +Portions Copyright (c) 1991-1995 Stichting Mathematisch Centrum, Amsterdam. +All Rights Reserved. """ From afa at codespeak.net Sat May 24 23:52:53 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Sat, 24 May 2008 23:52:53 +0200 (CEST) Subject: [pypy-svn] r55197 - pypy/dist/pypy/interpreter/astcompiler Message-ID: <20080524215253.F3E77169EDF@codespeak.net> Author: afa Date: Sat May 24 23:52:52 2008 New Revision: 55197 Modified: pypy/dist/pypy/interpreter/astcompiler/opt.py Log: This may depend on annotation order, but I regularly get this error:: Blocked block -- operation cannot succeed v0 = getattr(self_0, ('is_and')) Known variable annotations: self_0 = SomeInstance(can_be_None=False, classdef=pypy.interpreter.astcompiler.ast.AbstractTest) Attaching the attribute to the base class seems good practice anyway. Modified: pypy/dist/pypy/interpreter/astcompiler/opt.py ============================================================================== --- pypy/dist/pypy/interpreter/astcompiler/opt.py (original) +++ pypy/dist/pypy/interpreter/astcompiler/opt.py Sat May 24 23:52:52 2008 @@ -75,7 +75,7 @@ __metaclass__ = extendabletype is_and = True - class __extend__(ast.Or): + class __extend__(ast.AbstractTest): __metaclass__ = extendabletype is_and = False From santagada at codespeak.net Sun May 25 06:20:52 2008 From: santagada at codespeak.net (santagada at codespeak.net) Date: Sun, 25 May 2008 06:20:52 +0200 (CEST) Subject: [pypy-svn] r55199 - in pypy/branch/js-refactoring/pypy/lang/js: . bench Message-ID: <20080525042052.6D308169F27@codespeak.net> Author: santagada Date: Sun May 25 06:20:50 2008 New Revision: 55199 Modified: pypy/branch/js-refactoring/pypy/lang/js/astbuilder.py pypy/branch/js-refactoring/pypy/lang/js/bench/TODO.txt pypy/branch/js-refactoring/pypy/lang/js/interpreter.py pypy/branch/js-refactoring/pypy/lang/js/jsobj.py Log: fixes for Boolean objects, a nasty property 'de' propagation error, some intmask/float mistakes, a adition to benchmarks Modified: pypy/branch/js-refactoring/pypy/lang/js/astbuilder.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/astbuilder.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/astbuilder.py Sun May 25 06:20:50 2008 @@ -1,3 +1,4 @@ +from pypy.rlib.rarithmetic import intmask, ovfcheck from pypy.rlib.parsing.tree import RPythonVisitor, Symbol, Nonterminal from pypy.lang.js import operations from pypy.rlib.parsing.parsing import ParseError @@ -86,10 +87,10 @@ def visit_DECIMALLITERAL(self, node): pos = self.get_pos(node) try: - int(node.additional_info) - except ValueError: + ovfcheck(int(node.additional_info)) + except (ValueError, OverflowError): return operations.FloatNumber(pos, float(node.additional_info)) - return operations.IntNumber(pos, int(node.additional_info)) + return operations.IntNumber(pos, intmask(node.additional_info)) def visit_HEXINTEGERLITERAL(self, node): pos = self.get_pos(node) Modified: pypy/branch/js-refactoring/pypy/lang/js/bench/TODO.txt ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/bench/TODO.txt (original) +++ pypy/branch/js-refactoring/pypy/lang/js/bench/TODO.txt Sun May 25 06:20:50 2008 @@ -1,5 +1,8 @@ All benchmarks are from The Computer Language Benchmarks Game, licensed under the revised BSD License +Maybe we should also take a look at those benchmarks: + http://trac.webkit.org/projects/webkit/wiki/JavaScript%20and%20DOM%20Benchmarks + Parameters for the benchmarks: ackermann 9,10,11 Modified: pypy/branch/js-refactoring/pypy/lang/js/interpreter.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/interpreter.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/interpreter.py Sun May 25 06:20:50 2008 @@ -87,7 +87,7 @@ return W_String('') def Construct(self, ctx, args=[]): - if len(args) >= 1 and not isnull_or_undefined(args[0]): + if len(args) >= 1: Value = W_String(args[0].ToString(ctx)) return create_object(ctx, 'String', Value = Value) return create_object(ctx, 'String', Value = W_String('')) @@ -461,19 +461,20 @@ }) w_Boolean = W_BooleanObject('Boolean', w_FncPrototype) - w_Boolean.Put('constructor', w_FncPrototype) + w_Boolean.Put('constructor', w_FncPrototype, dd=True, ro=True, de=True) + w_Boolean.Put('length', W_IntNumber(1), dd=True, ro=True, de=True) w_BoolPrototype = create_object(ctx, 'Object', Value=W_Boolean(False)) w_BoolPrototype.Class = 'Boolean' put_values(w_BoolPrototype, { 'constructor': w_FncPrototype, - '__proto__': w_BoolPrototype, + '__proto__': w_ObjPrototype, 'toString': W_BooleanValueToString(ctx), - 'valueOf': get_value_of('Boolean', ctx) + 'valueOf': get_value_of('Boolean', ctx), }) - w_Boolean.Put('prototype', w_BoolPrototype) + w_Boolean.Put('prototype', w_BoolPrototype, dd=True, ro=True, de=True) w_Global.Put('Boolean', w_Boolean) Modified: pypy/branch/js-refactoring/pypy/lang/js/jsobj.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/jsobj.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/jsobj.py Sun May 25 06:20:50 2008 @@ -33,7 +33,7 @@ # return self def ToBoolean(self): - return False + raise NotImplementedError() def ToPrimitive(self, ctx, hint=""): return self @@ -86,7 +86,7 @@ def ToBoolean(self): return False - def ToString(self, ctx = None): + def ToString(self, ctx): return "undefined" def type(self): @@ -188,7 +188,7 @@ P.value = V except KeyError: self.propdict[P] = Property(P, V, - dd = dd, ro = ro, it = it) + dd = dd, ro = ro, de = de, it = it) def HasProperty(self, P): if P in self.propdict: return True @@ -223,6 +223,9 @@ ToPrimitive = DefaultValue + def ToBoolean(self): + return True + def ToString(self, ctx): try: res = self.ToPrimitive(ctx, 'String') @@ -390,7 +393,10 @@ return self.strval def ToBoolean(self): - return bool(self.strval) + if len(self.strval) == 0: + return False + else: + return True def type(self): return 'string' @@ -426,6 +432,7 @@ self.intval = intmask(intval) def ToString(self, ctx=None): + # XXX incomplete, this doesn't follow the 9.8.1 recommendation return str(self.intval) def ToBoolean(self): @@ -454,6 +461,7 @@ self.floatval = floatval def ToString(self, ctx = None): + # XXX incomplete, this doesn't follow the 9.8.1 recommendation if isnan(self.floatval): return 'NaN' if isinf(self.floatval): @@ -477,7 +485,7 @@ def ToInt32(self): if isnan(self.floatval) or isinf(self.floatval): return 0 - return int(self.floatval) + return intmask(self.floatval) def ToUInt32(self): if isnan(self.floatval) or isinf(self.floatval): From cfbolz at codespeak.net Sun May 25 10:34:15 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sun, 25 May 2008 10:34:15 +0200 (CEST) Subject: [pypy-svn] r55200 - pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk Message-ID: <20080525083415.E29F169804A@codespeak.net> Author: cfbolz Date: Sun May 25 10:34:14 2008 New Revision: 55200 Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/primitives.py Log: use is_same_object instead of is Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/primitives.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/primitives.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/primitives.py Sun May 25 10:34:14 2008 @@ -730,7 +730,7 @@ @expose_primitive(PRIMITIVE_SIGNAL, unwrap_spec=[object]) def func(interp, w_rcvr): # XXX we might want to disable this check - if w_rcvr.getclass() is not classtable.classtable['w_Semaphore']: + if not w_rcvr.getclass().is_same_object(classtable.classtable['w_Semaphore']): raise PrimitiveFailedError() wrapper.SemaphoreWrapper(w_rcvr).signal(interp) return w_rcvr @@ -738,7 +738,7 @@ @expose_primitive(PRIMITIVE_WAIT, unwrap_spec=[object]) def func(interp, w_rcvr): # XXX we might want to disable this check - if w_rcvr.getclass() is not classtable.classtable['w_Semaphore']: + if not w_rcvr.getclass().is_same_object(classtable.classtable['w_Semaphore']): raise PrimitiveFailedError() wrapper.SemaphoreWrapper(w_rcvr).wait(interp) return w_rcvr @@ -746,7 +746,7 @@ @expose_primitive(PRIMITIVE_RESUME, unwrap_spec=[object]) def func(interp, w_rcvr,): # XXX we might want to disable this check - if w_rcvr.getclass() is not classtable.classtable['w_Process']: + if not w_rcvr.getclass().is_same_object(classtable.classtable['w_Process']): raise PrimitiveFailedError() wrapper.ProcessWrapper(w_rcvr).resume(interp) return w_rcvr @@ -754,7 +754,7 @@ @expose_primitive(PRIMITIVE_SUSPEND, unwrap_spec=[object]) def func(interp, w_rcvr): # XXX we might want to disable this check - if w_rcvr.getclass() is not classtable.classtable['w_Process']: + if not w_rcvr.getclass().is_same_object(classtable.classtable['w_Process']): raise PrimitiveFailedError() wrapper.ProcessWrapper(w_rcvr).suspend(interp) return w_rcvr From cfbolz at codespeak.net Sun May 25 11:07:37 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sun, 25 May 2008 11:07:37 +0200 (CEST) Subject: [pypy-svn] r55201 - pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test Message-ID: <20080525090737.A331F169E72@codespeak.net> Author: cfbolz Date: Sun May 25 11:07:34 2008 New Revision: 55201 Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_interpreter.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_model.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_primitives.py Log: more of those Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_interpreter.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_interpreter.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_interpreter.py Sun May 25 11:07:34 2008 @@ -353,7 +353,7 @@ interp.step) w_fakeinst = interp.s_active_context().pop() assert interp.s_active_context().stack() == [] - assert w_fakeinst.getclass() == w_fakeclass + assert w_fakeinst.getclass().is_same_object(w_fakeclass) assert w_fakeinst.size() == 1 def test_bytecodePrimNewWithArg(): @@ -368,7 +368,7 @@ interp.step) w_fakeinst = interp.s_active_context().pop() assert interp.s_active_context().stack() == [] - assert w_fakeinst.getclass() == w_fakeclass + assert w_fakeinst.getclass().is_same_object(w_fakeclass) assert w_fakeinst.size() == 3 def test_bytecodePrimSize(): Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_model.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_model.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_model.py Sun May 25 11:07:34 2008 @@ -16,14 +16,14 @@ w_mycls = mockclass(0) w_myinstance = w_mycls.as_class_get_shadow().new() assert isinstance(w_myinstance, model.W_PointersObject) - assert w_myinstance.getclass() is w_mycls + assert w_myinstance.getclass().is_same_object(w_mycls) assert w_myinstance.shadow_of_my_class() is w_mycls.as_class_get_shadow() def test_new_namedvars(): w_mycls = mockclass(3) w_myinstance = w_mycls.as_class_get_shadow().new() assert isinstance(w_myinstance, model.W_PointersObject) - assert w_myinstance.getclass() is w_mycls + assert w_myinstance.getclass().is_same_object(w_mycls) assert w_myinstance.fetch(0) is objtable.w_nil py.test.raises(IndexError, lambda: w_myinstance.fetch(3)) w_myinstance.store(1, w_myinstance) @@ -32,7 +32,7 @@ def test_bytes_object(): w_class = mockclass(0, format=shadow.BYTES) w_bytes = w_class.as_class_get_shadow().new(20) - assert w_bytes.getclass() is w_class + assert w_bytes.getclass().is_same_object(w_class) assert w_bytes.size() == 20 assert w_class.as_class_get_shadow().instsize() == 0 assert w_bytes.getchar(3) == "\x00" @@ -44,7 +44,7 @@ def test_word_object(): w_class = mockclass(0, format=shadow.WORDS) w_bytes = w_class.as_class_get_shadow().new(20) - assert w_bytes.getclass() is w_class + assert w_bytes.getclass().is_same_object(w_class) assert w_bytes.size() == 20 assert w_class.as_class_get_shadow().instsize() == 0 assert w_bytes.getword(3) == 0 @@ -181,8 +181,8 @@ assert w_a.gethash() == hashb assert w_b.gethash() == hasha - assert w_a.getclass() is w_clsb - assert w_b.getclass() is w_clsa + assert w_a.getclass().is_same_object(w_clsb) + assert w_b.getclass().is_same_object(w_clsa) assert w_b.fetch(0) is w_b assert w_a.fetch(1) is w_a Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_primitives.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_primitives.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_primitives.py Sun May 25 11:07:34 2008 @@ -246,14 +246,14 @@ def test_new(): w_Object = classtable.classtable['w_Object'] w_res = prim(primitives.NEW, [w_Object]) - assert w_res.getclass() is w_Object + assert w_res.getclass().is_same_object(w_Object) def test_invalid_new(): prim_fails(primitives.NEW, [classtable.w_String]) def test_new_with_arg(): w_res = prim(primitives.NEW_WITH_ARG, [classtable.w_String, 20]) - assert w_res.getclass() == classtable.w_String + assert w_res.getclass().is_same_object(classtable.w_String) assert w_res.size() == 20 def test_invalid_new_with_arg(): From cami at codespeak.net Sun May 25 11:41:21 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Sun, 25 May 2008 11:41:21 +0200 (CEST) Subject: [pypy-svn] r55202 - in pypy/dist/pypy/lang/gameboy: . test Message-ID: <20080525094121.5E5D1698051@codespeak.net> Author: cami Date: Sun May 25 11:41:15 2008 New Revision: 55202 Modified: pypy/dist/pypy/lang/gameboy/cartridge.py pypy/dist/pypy/lang/gameboy/cpu.py pypy/dist/pypy/lang/gameboy/test/test_memory_bank_controller.py pypy/dist/pypy/lang/gameboy/video.py Log: added tests for MBC3, MBC5 and HuC1 Cartridge types fixed a bug in the HuC1 cartridge fixed a bug in test_mbc Modified: pypy/dist/pypy/lang/gameboy/cartridge.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/cartridge.py (original) +++ pypy/dist/pypy/lang/gameboy/cartridge.py Sun May 25 11:41:15 2008 @@ -243,7 +243,7 @@ def __init__(self, rom, ram, clock_driver, min_rom_bank_size=0, max_rom_bank_size=0, min_ram_bank_size=0, max_ram_bank_size=0): - self.clock = clock_driver + self.clock = clock_driver self.min_rom_bank_size = min_rom_bank_size self.max_rom_bank_size = max_rom_bank_size self.min_ram_bank_size = min_ram_bank_size @@ -295,6 +295,10 @@ def write(self, address, data): raise Exception("MBC: Invalid write access") + + def write_ram_enable(self, address, data): + if self.ram_size > 0: + self.ram_enable = ((data & 0x0A) == 0x0A) #------------------------------------------------------------------------------- @@ -351,10 +355,6 @@ else: raise Exception("Invalid memory Access address: %s" % hex(address)) - def write_ram_enable(self, address, data): - if self.ram_size > 0: - self.ram_enable = ((data & 0x0A) == 0x0A) - def write_rom_bank_1(self, address, data): if (data & 0x1F) == 0: data = 1 @@ -415,10 +415,6 @@ elif address >= 0xA000 and address <= 0xA1FF: # A000-A1FF self.write_ram(address, data) - def write_ram_enable(self, address, data): - if (address & 0x0100) == 0: - self.ram_enable = ((data & 0x0A) == 0x0A) - def write_rom_bank(self, address, data): if (address & 0x0100) == 0: return @@ -429,7 +425,10 @@ def write_ram(self, address, data): if self.ram_enable: self.ram[address & 0x01FF] = data & 0x0F - + + def write_ram_enable(self, address, data): + if (address & 0x0100) == 0: + self.ram_enable = ((data & 0x0A) == 0x0A) #------------------------------------------------------------------------------- @@ -455,14 +454,14 @@ def reset(self): MBC.reset(self) self.clock_latched_daysclock_latched_control = None - self.clock_time = self.clock.get_time() - self.clock_latch = 0 - self.clock_register = 0 - self.clock_seconds = 0 - self.clock_minutes = 0 - self.clock_hours = 0 - self.clock_days = 0 - self.clock_control = 0 + self.clock_time = self.clock.get_time() + self.clock_latch = 0 + self.clock_register = 0 + self.clock_seconds = 0 + self.clock_minutes = 0 + self.clock_hours = 0 + self.clock_days = 0 + self.clock_control = 0 self.clock_latched_seconds = 0 self.clock_latched_minutes = 0 self.clock_latched_hours = 0 @@ -504,10 +503,6 @@ elif address >= 0xA000 and address <= 0xBFFF and self.ram_enable: # A000-BFFF self.write_clock_data(address, data) - def write_ram_enable(self, address, data): - if self.ram_size > 0: - self.ram_enable = ((data & 0x0A) == 0x0A) - def write_rom_bank(self, address, data): if data == 0: data = 1 @@ -608,7 +603,7 @@ def write(self, address, data): address = int(address) - if address <= self.ram_enable: # 0000-1FFF + if address <= 0x1FFF: # 0000-1FFF self.write_ram_enable(address, data) elif address <= 0x2FFF: # 2000-2FFF self.rom_bank = ((self.rom_bank & (0x01 << 22)) + \ @@ -621,10 +616,6 @@ elif address >= 0xA000 and address <= 0xBFFF and self.ram_enable: # A000-BFFF self.ram[self.ram_bank + (address & 0x1FFF)] = data - def write_ram_enable(self, address, data): - if self.ram_size > 0: - self.ram_enable = ((data & 0x0A) == 0x0A) - def write_ram_bank(self, address, data): if self.rumble: self.ram_bank = ((data & 0x07) << 13) & self.ram_size @@ -635,10 +626,9 @@ #------------------------------------------------------------------------------- -class HuC1(MBC): - def __init__(self, ram, rom, clock_driver): - self.reset() - MBC.__init__(self, rom, ram, clock_driver) +class HuC1(MBC1): + def __init__(self, rom, ram, clock_driver): + MBC1.__init__(self, rom, ram, clock_driver) @@ -666,11 +656,11 @@ def reset(self): MBC.reset(self) - self.ram_flag = 0 - self.ram_value = 0 + self.ram_flag = 0 + self.ram_value = 0 self.clock_register = 0 - self.clock_shift = 0 - self.clock_time = self.clock.get_time() + self.clock_shift = 0 + self.clock_time = self.clock.get_time() def read(self, address): Modified: pypy/dist/pypy/lang/gameboy/cpu.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/cpu.py (original) +++ pypy/dist/pypy/lang/gameboy/cpu.py Sun May 25 11:41:15 2008 @@ -389,7 +389,8 @@ def fetch_execute(self): # Execution opCode = self.fetch() - print " fetch exe:", hex(opCode), " ", FETCH_EXECUTE_OP_CODES[opCode].__name__ + print " fetch exe:", hex(opCode), " " + #, FETCH_EXECUTE_OP_CODES[opCode].__name__ self.last_fetch_execute_op_code = opCode FETCH_EXECUTE_OP_CODES[opCode](self) @@ -397,7 +398,8 @@ def execute(self, opCode): self.instruction_counter += 1 print self.instruction_counter, "-"*60 - print "exe: ", hex(opCode), " ", OP_CODES[opCode].__name__ + print "exe: ", hex(opCode), " " + #, OP_CODES[opCode].__name__ print " pc:", hex(self.pc.get()), "sp:", hex(self.sp.get()) self.print_registers() self.last_op_code = opCode Modified: pypy/dist/pypy/lang/gameboy/test/test_memory_bank_controller.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/test/test_memory_bank_controller.py (original) +++ pypy/dist/pypy/lang/gameboy/test/test_memory_bank_controller.py Sun May 25 11:41:15 2008 @@ -64,7 +64,7 @@ def write_ram_enable_test(mbc): value = 0 for address in range(0x1FFF+1): - mbc.write(address, 0x0A) + mbc.write(address, 0xFF) assert mbc.ram_enable == True mbc.write(address, 0x00) assert mbc.ram_enable == False @@ -94,8 +94,7 @@ pass def test_mbc(): - py.test.skip() - mbc = MBC(get_ram(), get_rom(), get_clock_driver(),1, 0xF3, 2, 0xF1) + mbc = MBC(get_rom(2), get_ram(2), get_clock_driver(),1, 0xF3, 2, 0xF1) assert mbc.min_rom_bank_size == 1 assert mbc.max_rom_bank_size == 0xF3 assert mbc.min_ram_bank_size == 2 @@ -103,10 +102,10 @@ assert mbc.rom_bank == constants.ROM_BANK_SIZE assert mbc.ram_bank == 0 assert mbc.ram_enable == False - assert mbc.rom_size == ROM_SIZE * constants.ROM_BANK_SIZE - 1 - assert mbc.ram_size == RAM_SIZE * constants.ROM_BANK_SIZE - 1 - assert len(mbc.rom) == ROM_SIZE - assert len(mbc.ram) == RAM_SIZE + assert mbc.rom_size == 2*constants.ROM_BANK_SIZE - 1 + assert mbc.ram_size == 2*constants.RAM_BANK_SIZE - 1 + assert len(mbc.rom) == constants.ROM_BANK_SIZE * 2 + assert len(mbc.ram) == constants.RAM_BANK_SIZE * 2 def test_mbc_read_write(): @@ -166,24 +165,28 @@ def get_mbc1(rom_size=128, ram_size=4): return MBC1(get_rom(rom_size), get_ram(ram_size), get_clock_driver()) -def test_mbc1(): - mbc1 = get_mbc1() - assert mbc1.rom_bank == constants.ROM_BANK_SIZE - assert mbc1.memory_model == 0 - assert mbc1.ram_enable == False - assert mbc1.ram_bank == 0 - fail_ini_test(get_mbc1, 128, 5) - fail_ini_test(get_mbc1, 128, -1) - fail_ini_test(get_mbc1, 1, 4) - fail_ini_test(get_mbc1, 129, 4) - - basic_read_write_test(mbc1, 0, 0x7FFF) - -def test_mbc1_write_ram_enable(): - write_ram_enable_test(get_mbc1()) - -def test_mbc_write_rom_bank_test1(): - mbc= get_mbc1() +def test_mbc1(mbc=None): + if mbc is None: + mbc = get_mbc1() + assert mbc.rom_bank == constants.ROM_BANK_SIZE + assert mbc.memory_model == 0 + assert mbc.ram_enable == False + assert mbc.ram_bank == 0 + fail_ini_test(mbc, 128, 5) + fail_ini_test(mbc, 128, -1) + fail_ini_test(mbc, 1, 4) + fail_ini_test(mbc, 129, 4) + + basic_read_write_test(mbc, 0, 0x7FFF) + +def test_mbc1_write_ram_enable(mbc=None): + if mbc is None: + mbc = get_mbc1() + write_ram_enable_test(mbc) + +def test_mbc1_write_rom_bank_test1(mbc=None): + if mbc is None: + mbc = get_mbc1() value = 1 for address in range(0x2000, 0x3FFF+1): mbc.memory_model = 0 @@ -196,8 +199,9 @@ assert mbc.rom_bank == ((value & 0x1F) << 14) & mbc.rom_size value = (value+1) % (0x1F-1) +1 -def test_mbc1_write_rom_bank_test2(): - mbc = get_mbc1() +def test_mbc1_write_rom_bank_test2(mbc=None): + if mbc is None: + mbc = get_mbc1() value = 1 for address in range(0x4000, 0x5FFF+1): mbc.memory_model = 0 @@ -211,8 +215,9 @@ value += 1 value %= 0xFF -def test_mbc1_read_memory_model(): - mbc = get_mbc1() +def test_mbc1_read_memory_model(mbc=None): + if mbc is None: + mbc = get_mbc1() value = 1 for address in range(0x6000, 0x7FFF+1): mbc.write(address, value) @@ -220,8 +225,9 @@ value += 1 value %= 0xFF -def test_mbc1_read_write_ram(): - mbc = get_mbc1() +def test_mbc1_read_write_ram(mbc=None): + if mbc is None: + mbc = get_mbc1() value = 1 mbc.ram_enable = True for address in range(0xA000, 0xBFFF+1): @@ -238,13 +244,13 @@ return MBC2(get_rom(rom_size), get_ram(ram_size), get_clock_driver()) def test_mbc2_create(): - mbc2 = get_mbc2() - fail_ini_test(mbc2, 2, 0) - fail_ini_test(mbc2, 2, 2) - fail_ini_test(mbc2, 1, 1) - fail_ini_test(mbc2, 17, 1) + mbc = get_mbc2() + fail_ini_test(mbc, 2, 0) + fail_ini_test(mbc, 2, 2) + fail_ini_test(mbc, 1, 1) + fail_ini_test(mbc, 17, 1) # only to the upper border of mbc - basic_read_write_test(mbc2, 0, 0x7FFF) + basic_read_write_test(mbc, 0, 0x7FFF) def test_mbc2_write_ram_enable(): @@ -289,12 +295,12 @@ return MBC3(get_rom(rom_size), get_ram(ram_size), get_clock_driver()) def test_mbc3_create(): - mbc3 = get_mbc3() - fail_ini_test(mbc3, 128, -1) - fail_ini_test(mbc3, 128, 5) - fail_ini_test(mbc3, 1, 4) - fail_ini_test(mbc3, 129, 4) - basic_read_write_test(mbc3, 0, 0x7FFF) + mbc = get_mbc3() + fail_ini_test(mbc, 128, -1) + fail_ini_test(mbc, 128, 5) + fail_ini_test(mbc, 1, 4) + fail_ini_test(mbc, 129, 4) + basic_read_write_test(mbc, 0, 0x7FFF) def test_mbc3_write_ram_enable(): write_ram_enable_test(get_mbc3()) @@ -399,19 +405,57 @@ return MBC5(get_rom(rom_size), get_ram(ram_size), get_clock_driver()) def test_mbc5_create(): - get_mbc5() - fail_ini_test(get_mbc5, 512, -1) - fail_ini_test(get_mbc5, 512, 17) - fail_ini_test(get_mbc5, 1, 16) - fail_ini_test(get_mbc5, 513, 16) + mbc = get_mbc5() + fail_ini_test(mbc, 512, -1) + fail_ini_test(mbc, 512, 17) + fail_ini_test(mbc, 1, 16) + fail_ini_test(mbc, 513, 16) -def test_mbc5_read(): - py.test.skip("not yet implemented") - mbc5 = get_mbc5() - -def test_mbc5_write(): - py.test.skip("not yet implemented") - mbc5 = get_mbc5() +def test_mbc5_write_ram_enable(): + write_ram_enable_test(get_mbc5()) + +def test_mbc5_write_rom_bank_test1(): + mbc= get_mbc5() + value = 1 + for address in range(0x2000, 0x2FFF+1): + rom_bank = mbc.rom_bank + mbc.write(address, value) + assert mbc.rom_bank == ((rom_bank & (0x01 << 22)) + \ + ((value & 0xFF) << 14)) & mbc.rom_size + value = (value+1) % (0x1F-1) +1 + +def test_mbc5_write_rom_bank_test2(): + mbc = get_mbc5() + value = 1 + for address in range(0x3000, 0x3FFF+1): + rom_bank = mbc.rom_bank + mbc.write(address, value) + assert mbc.rom_bank == ((rom_bank & (0xFF << 14)) + \ + ((value & 0x01) << 22)) & mbc.rom_size + value = (value+1) % (0x1F-1) +1 + +def test_mbc5_write_ram_bank(): + mbc = get_mbc5() + value = 1 + for address in range(0x4000, 0x4FFF+1): + mbc.rumble = True + mbc.write(address, value) + assert mbc.ram_bank == ((value & 0x07) << 13) & mbc.ram_size + mbc.rumble = False + mbc.write(address, value) + assert mbc.ram_bank == ((value & 0x0F) << 13) & mbc.ram_size + value = (value+1) % (0x1F-1) +1 + +def test_mbc5_read_write_ram(): + mbc = get_mbc5() + value = 1 + mbc.ram_enable = True + for address in range(0xA000, 0xBFFF+1): + mbc.write(address, value) + assert mbc.ram[mbc.ram_bank + (address & 0x1FFF)] == value + assert mbc.read(address) == value; + value += 1 + value %= 0xFF # ----------------------------------------------------------------------------- @@ -419,19 +463,22 @@ return HuC1(get_rom(rom_size), get_ram(ram_size), get_clock_driver()) def test_huc1_create(): - get_huc1() - fail_ini_test(get_huc1, 128, 5) - fail_ini_test(get_huc1, 128, -1) - fail_ini_test(get_huc1, 1, 4) - fail_ini_test(get_huc1, 129, 4) + test_mbc1_create(get_huc1()) -def test_huc1_read(): - py.test.skip("not yet implemented") - huc1 = get_huc1() - -def test_huc1_write(): - py.test.skip("not yet implemented") - huc1 = get_huc1() +def test_huc1_write_ram_enable(): + test_mbc1_write_ram_enable(get_huc1()) + +def test_huc1_write_rom_bank_test1(): + test_mbc1_write_rom_bank_test1(get_huc1()) + +def test_huc1_write_rom_bank_test2(): + test_mbc1_write_rom_bank_test2(get_huc1()) + +def test_huc1_read_memory_model(): + test_mbc1_read_memory_model(get_huc1()) + +def test_huc1_read_write_ram(): + test_mbc1_read_write_ram(get_huc1()) # ----------------------------------------------------------------------------- Modified: pypy/dist/pypy/lang/gameboy/video.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/video.py (original) +++ pypy/dist/pypy/lang/gameboy/video.py Sun May 25 11:41:15 2008 @@ -53,15 +53,20 @@ def reset(self): self.cycles = constants.MODE_2_TICKS + # used for enabled or disablind window or background self.control = 0x91 self.stat = 2 self.line_y = 0 self.line_y_compare = 0 self.dma = 0xFF - self.scroll_y = 0 + # SCROLLX and SCROLLY hold the coordinates of background to + # be displayed in the left upper corner of the screen. self.scroll_x = 0 - self.window_y = self.wline_y = 0 + self.scroll_y = 0 + # window position self.window_x = 0 + self.window_y = 0 + self.wline_y = 0 self.background_palette = 0xFC self.object_palette_0 = 0xFF self.object_palette_1 = 0xFF From cami at codespeak.net Sun May 25 12:08:45 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Sun, 25 May 2008 12:08:45 +0200 (CEST) Subject: [pypy-svn] r55203 - pypy/dist/pypy/lang/gameboy/test Message-ID: <20080525100845.8A396169EBC@codespeak.net> Author: cami Date: Sun May 25 12:08:42 2008 New Revision: 55203 Modified: pypy/dist/pypy/lang/gameboy/test/test_memory_bank_controller.py Log: added tests for huc3 Modified: pypy/dist/pypy/lang/gameboy/test/test_memory_bank_controller.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/test/test_memory_bank_controller.py (original) +++ pypy/dist/pypy/lang/gameboy/test/test_memory_bank_controller.py Sun May 25 12:08:42 2008 @@ -165,7 +165,7 @@ def get_mbc1(rom_size=128, ram_size=4): return MBC1(get_rom(rom_size), get_ram(ram_size), get_clock_driver()) -def test_mbc1(mbc=None): +def test_mbc1_create(mbc=None): if mbc is None: mbc = get_mbc1() assert mbc.rom_bank == constants.ROM_BANK_SIZE @@ -393,7 +393,6 @@ py.test.skip("not yet implemented") mbc = get_mbc3() - def test_mbc3_latch_clock(): py.test.skip("not yet implemented") mbc = get_mbc3() @@ -485,20 +484,115 @@ def get_huc3(rom_size=128, ram_size=4): return HuC3(get_rom(rom_size), get_ram(ram_size), get_clock_driver()) -def test_huc1_create(): - get_huc3() - fail_ini_test(get_huc3, 128, 5) - fail_ini_test(get_huc3, 128, -1) - fail_ini_test(get_huc3, 1, 4) - fail_ini_test(get_huc3, 129, 4) - -def test_huc3_read(): - py.test.skip("not yet implemented") - huc3 = get_huc3() +def test_huc3_create(): + mbc = get_huc3() + fail_ini_test(mbc, 128, 5) + fail_ini_test(mbc, 128, -1) + fail_ini_test(mbc, 1, 4) + fail_ini_test(mbc, 129, 4) -def test_huc3_write(): +def test_huc3_write_ram_flag(): + mbc= get_huc3() + value = 1 + for address in range(0x0000, 0x1FFF+1): + mbc.write(address, value) + assert mbc.ram_flag == value + value = +1 + value %= 0xFF + +def test_huc3_write_rom_bank(): + mbc= get_huc3() + value = 1 + for address in range(0x2000, 0x3FFF+1): + mbc.write(address, value) + if (value & 0x7F) == 0: + assert mbc.rom_bank == ((1 & 0x7F) << 14) & mbc.rom_size + else: + assert mbc.rom_bank == ((value & 0x7F) << 14) & mbc.rom_size + value = +1 + value %= 0xFF + +def test_huc3_write_ram_bank(): + mbc = get_huc3() + value = 1 + for address in range(0x4000, 0x5FFF+1): + mbc.write(address, value) + assert mbc.ram_bank == ((value & 0x0F) << 13) & mbc.rom_size + value = +1 + value %= 0xFF + +def test_huc3_write_ram(): + mbc = get_huc3() + value = 1 + mbc.ram_flag = 0x0A + for address in range(0xA000, 0xBFFF+1): + mbc.write(address, value) + assert mbc.ram[mbc.ram_bank + (address & 0x1FFF)] == value + value = +1 + value %= 0xFF + +def test_huc3_write_ram_value(): + mbc = get_huc3() + mbc.ram_flag = 0x0B + for address in range(0xA000, 0xBFFF+1): + clock_shift = mbc.clock_shift + mbc.write(address, 0x10) + if clock_shift <= 24: + assert mbc.ram_value == (mbc.clock_register >> clock_shift) & 0x0F + assert mbc.clock_shift == clock_shift+4 + else: + assert mbc.clock_shift == clock_shift + mbc.clock_shift = 0 + +def test_huc3_write_reset_ram_value(): + mbc = get_huc3() + value = 1 + mbc.ram_flag = 0x0B + for address in range(0xA000, 0xBFFF+1): + mbc.ram_value == value + mbc.write(address, 0x60) + assert mbc.ram_value == 0x01 + value = +1 + value %= 0xFF + +def test_huc3_write_clock_register(): + mbc = get_huc3() + value = 1 + mbc.ram_flag = 0x0B + for address in range(0xA000, 0xBFFF+1): + clock_shift = mbc.clock_shift + clock_register = mbc.clock_register + mbc.write(address, 0x30+value) + if clock_shift <= 24: + assert mbc.clock_register == (clock_register & \ + ~(0x0F << clock_shift)) | \ + (value << clock_shift) + assert mbc.clock_shift == clock_shift+4 + else: + assert mbc.clock_shift == clock_shift + mbc.clock_shift = 0 + value = +1 + value %= 0xF + +def test_huc3_write_update_clock(): + mbc = get_huc3() + value = 1 + mbc.ram_flag = 0x0B + for address in range(0xA000, 0xBFFF+1): + mbc.ram_value == value + mbc.clock_shift = 1 + mbc.write(address, 0x40+value) + if value==0x00 or value==0x03 or value==0x07: + assert mbc.clock_shift == 0 + else: + assert mbc.clock_shift == 1 + value = +1 + value %= 0xF + +def test_huc3_update_clock(): py.test.skip("not yet implemented") - huc3 = get_huc3() + mbc = get_huc3() + pass # ----------------------------------------------------------------------------- From cfbolz at codespeak.net Sun May 25 16:09:10 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sun, 25 May 2008 16:09:10 +0200 (CEST) Subject: [pypy-svn] r55204 - in pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk: . test Message-ID: <20080525140910.C8774169E3D@codespeak.net> Author: cfbolz Date: Sun May 25 16:09:07 2008 New Revision: 55204 Added: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/space.py (contents, props changed) pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_objectspace.py - copied, changed from r55192, pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_classtable.py Removed: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/classtable.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/objtable.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_classtable.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/utility.py Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/interpreter.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/primitives.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/squeakimage.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_interpreter.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_miniimage.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_model.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_primitives.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_shadow.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_squeakimage.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_wrapper.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/wrapper.py Log: huge refactoring to introduce an "object space" that holds all globally accessible objects and has helper functionality. No the interpreter has no globals any more. On the other hand, the space needs to be passed a bit everywhere. Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/interpreter.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/interpreter.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/interpreter.py Sun May 25 16:09:07 2008 @@ -1,7 +1,6 @@ import py from pypy.lang.smalltalk.shadow import ContextPartShadow, MethodContextShadow, BlockContextShadow from pypy.lang.smalltalk import model, constants, primitives -from pypy.lang.smalltalk import objtable from pypy.lang.smalltalk.shadow import ContextPartShadow from pypy.lang.smalltalk.conftest import option from pypy.rlib import objectmodel, unroll @@ -19,18 +18,11 @@ class Interpreter(object): - TRUE = objtable.w_true - FALSE = objtable.w_false - NIL = objtable.w_nil - MINUS_ONE = objtable.w_minus_one - ZERO = objtable.w_zero - ONE = objtable.w_one - TWO = objtable.w_two - _w_last_active_context = None - def __init__(self): + def __init__(self, space): self._w_active_context = None + self.space = space self.cnt = 0 def w_active_context(self): @@ -41,7 +33,7 @@ self._w_active_context = w_context def s_active_context(self): - return self.w_active_context().as_context_get_shadow() + return self.w_active_context().as_context_get_shadow(self.space) def interpret(self): try: @@ -65,11 +57,11 @@ cnt = 0 p = self.w_active_context() # AK make method - while p is not objtable.w_nil: + while p is not self.space.w_nil: cnt += 1 # Do not update the context # for this action. - p = p.as_context_get_shadow().w_sender() + p = p.as_context_get_shadow(self.space).w_sender() self._last_indent = " " * cnt self._w_last_active_context = self.w_active_context() @@ -124,7 +116,7 @@ # named var (the value). index = self.currentBytecode & 31 w_association = self.w_method().getliteral(index) - association = wrapper.AssociationWrapper(w_association) + association = wrapper.AssociationWrapper(self.space, w_association) self.push(association.value()) def storeAndPopReceiverVariableBytecode(self, interp): @@ -140,25 +132,25 @@ self.push(self.w_receiver()) def pushConstantTrueBytecode(self, interp): - self.push(interp.TRUE) + self.push(interp.space.w_true) def pushConstantFalseBytecode(self, interp): - self.push(interp.FALSE) + self.push(interp.space.w_false) def pushConstantNilBytecode(self, interp): - self.push(interp.NIL) + self.push(interp.space.w_nil) def pushConstantMinusOneBytecode(self, interp): - self.push(interp.MINUS_ONE) + self.push(interp.space.w_minus_one) def pushConstantZeroBytecode(self, interp): - self.push(interp.ZERO) + self.push(interp.space.w_zero) def pushConstantOneBytecode(self, interp): - self.push(interp.ONE) + self.push(interp.space.w_one) def pushConstantTwoBytecode(self, interp): - self.push(interp.TWO) + self.push(interp.space.w_two) def pushActiveContextBytecode(self, interp): self.push(self.w_self()) @@ -175,12 +167,12 @@ def _sendSelfSelector(self, selector, argcount, interp): receiver = self.peek(argcount) self._sendSelector(selector, argcount, interp, - receiver, receiver.shadow_of_my_class()) + receiver, receiver.shadow_of_my_class(self.space)) def _sendSuperSelector(self, selector, argcount, interp): w_compiledin = self.w_method().compiledin() assert isinstance(w_compiledin, model.W_PointersObject) - s_compiledin = w_compiledin.as_class_get_shadow() + s_compiledin = w_compiledin.as_class_get_shadow(self.space) self._sendSelector(selector, argcount, interp, self.w_receiver(), s_compiledin.s_superclass()) @@ -219,28 +211,29 @@ print "PRIMITIVE FAILED: %d %s" % (method.primitive, selector,) pass # ignore this error and fall back to the Smalltalk version arguments = self.pop_and_return_n(argcount) - interp.store_w_active_context(method.create_frame(receiver, arguments, - self.w_self())) + frame = method.create_frame(self.space, receiver, arguments, + self.w_self()) + interp.store_w_active_context(frame) self.pop() def _return(self, object, interp, w_return_to): # for tests, when returning from the top-level context - if w_return_to is objtable.w_nil: + if w_return_to is self.space.w_nil: raise ReturnFromTopLevel(object) - w_return_to.as_context_get_shadow().push(object) + w_return_to.as_context_get_shadow(self.space).push(object) interp.store_w_active_context(w_return_to) def returnReceiver(self, interp): self._return(self.w_receiver(), interp, self.s_home().w_sender()) def returnTrue(self, interp): - self._return(interp.TRUE, interp, self.s_home().w_sender()) + self._return(interp.space.w_true, interp, self.s_home().w_sender()) def returnFalse(self, interp): - self._return(interp.FALSE, interp, self.s_home().w_sender()) + self._return(interp.space.w_false, interp, self.s_home().w_sender()) def returnNil(self, interp): - self._return(interp.NIL, interp, self.s_home().w_sender()) + self._return(interp.space.w_nil, interp, self.s_home().w_sender()) def returnTopFromMethod(self, interp): self._return(self.top(), interp, self.s_home().w_sender()) @@ -266,7 +259,7 @@ self.push(self.w_method().getliteral(variableIndex)) elif variableType == 3: w_association = self.w_method().getliteral(variableIndex) - association = wrapper.AssociationWrapper(w_association) + association = wrapper.AssociationWrapper(self.space, w_association) self.push(association.value()) else: assert 0 @@ -281,7 +274,7 @@ raise IllegalStoreError elif variableType == 3: w_association = self.w_method().getliteral(variableIndex) - association = wrapper.AssociationWrapper(w_association) + association = wrapper.AssociationWrapper(self.space, w_association) association.store_value(self.top()) def extendedStoreAndPopBytecode(self, interp): @@ -318,7 +311,7 @@ elif opType == 4: # pushLiteralVariable w_association = self.w_method().getliteral(third) - association = wrapper.AssociationWrapper(w_association) + association = wrapper.AssociationWrapper(self.space, w_association) self.push(association.value()) elif opType == 5: self.w_receiver().store(third, self.top()) @@ -326,7 +319,7 @@ self.w_receiver().store(third, self.pop()) elif opType == 7: w_association = self.w_method().getliteral(third) - association = wrapper.AssociationWrapper(w_association) + association = wrapper.AssociationWrapper(self.space, w_association) association.store_value(self.top()) def singleExtendedSuperBytecode(self, interp): @@ -360,7 +353,7 @@ self.jump(self.shortJumpPosition()) def shortConditionalJump(self, interp): - self.jumpConditional(interp.FALSE,self.shortJumpPosition()) + self.jumpConditional(interp.space.w_false, self.shortJumpPosition()) def longUnconditionalJump(self, interp): self.jump((((self.currentBytecode & 7) - 4) << 8) + self.getbytecode()) @@ -369,10 +362,10 @@ return ((self.currentBytecode & 3) << 8) + self.getbytecode() def longJumpIfTrue(self, interp): - self.jumpConditional(interp.TRUE,self.longJumpPosition()) + self.jumpConditional(interp.space.w_true, self.longJumpPosition()) def longJumpIfFalse(self, interp): - self.jumpConditional(interp.FALSE,self.longJumpPosition()) + self.jumpConditional(interp.space.w_false, self.longJumpPosition()) # RPython trick: specialize the following function on its second argument # this makes sure that the primitive call is a direct one Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py Sun May 25 16:09:07 2008 @@ -33,17 +33,17 @@ space, as memory representation varies depending on PyPy translation.""" return 0 - def varsize(self): + def varsize(self, space): """Return bytesize of variable-sized part. Variable sized objects are those created with #new:.""" - return self.size() + return self.size(space) - def primsize(self): + def primsize(self, space): # TODO remove this method return self.size() - def getclass(self): + def getclass(self, space): """Return Squeak class.""" raise NotImplementedError() @@ -51,7 +51,7 @@ """Return 31-bit hash value.""" raise NotImplementedError() - def at0(self, index0): + def at0(self, space, index0): """Access variable-sized part, as by Object>>at:. Return value depends on layout of instance. Byte objects return bytes, @@ -60,7 +60,7 @@ otherwise returns byte (ie byte code indexing starts at literalsize).""" raise NotImplementedError() - def atput0(self, index0, w_value): + def atput0(self, space, index0, w_value): """Access variable-sized part, as by Object>>at:put:. Semantics depend on layout of instance. Byte objects set bytes, @@ -83,9 +83,9 @@ def invariant(self): return True - def shadow_of_my_class(self): + def shadow_of_my_class(self, space): """Return internal representation of Squeak class.""" - return self.getclass().as_class_get_shadow() + return self.getclass(space).as_class_get_shadow(space) def is_same_object(self, other): """Compare object identity""" @@ -104,10 +104,9 @@ def __init__(self, value): self.value = value - def getclass(self): + def getclass(self, space): """Return SmallInteger from special objects array.""" - from pypy.lang.smalltalk.classtable import w_SmallInteger - return w_SmallInteger + return space.w_SmallInteger def gethash(self): return self.value @@ -141,10 +140,9 @@ def __init__(self, value): self.value = value - def getclass(self): + def getclass(self, space): """Return Float from special objects array.""" - from pypy.lang.smalltalk.classtable import w_Float - return w_Float + return space.w_Float def gethash(self): return 41 # XXX check this @@ -208,7 +206,7 @@ assert isinstance(w_class, W_PointersObject) self.w_class = w_class - def getclass(self): + def getclass(self, space): assert self.w_class is not None return self.w_class @@ -219,7 +217,10 @@ if isinstance(self, W_PointersObject) and self._shadow is not None: return self._shadow.getname() else: - return "a %s" % (self.shadow_of_my_class().name or '?',) + name = None + if self.w_class._shadow is not None: + name = self.w_class._shadow.name + return "a %s" % (name or '?',) def invariant(self): return (W_AbstractObjectWithIdentityHash.invariant(self) and @@ -242,13 +243,13 @@ W_AbstractObjectWithClassReference.__init__(self, w_class) self._vars = [w_nil] * size - def at0(self, index0): + def at0(self, space, index0): # To test, at0 = in varsize part - return self.fetch(index0+self.instsize()) + return self.fetch(index0+self.instsize(space)) - def atput0(self, index0, w_value): + def atput0(self, space, index0, w_value): # To test, at0 = in varsize part - self.store(index0+self.instsize(), w_value) + self.store(index0+self.instsize(space), w_value) def fetch(self, n0): if self._shadow is not None: @@ -272,14 +273,14 @@ # def storevarpointer(self, idx, value): # self._vars[idx+self.instsize()] = value - def varsize(self): - return self.size() - self.instsize() + def varsize(self, space): + return self.size() - self.instsize(space) - def instsize(self): - return self.shadow_of_my_class().instsize() + def instsize(self, space): + return self.shadow_of_my_class(space).instsize() - def primsize(self): - return self.varsize() + def primsize(self, space): + return self.varsize(space) def size(self): if self._shadow is not None: @@ -296,52 +297,52 @@ def store_shadow(self, shadow): self._shadow = shadow - @objectmodel.specialize.arg(1) - def attach_shadow_of_class(self, TheClass): - shadow = TheClass(self) + @objectmodel.specialize.arg(2) + def attach_shadow_of_class(self, space, TheClass): + shadow = TheClass(space, self) self._shadow = shadow shadow.attach_shadow() return shadow - @objectmodel.specialize.arg(1) - def as_special_get_shadow(self, TheClass): + @objectmodel.specialize.arg(2) + def as_special_get_shadow(self, space, TheClass): shadow = self._shadow if shadow is None: - shadow = self.attach_shadow_of_class(TheClass) + shadow = self.attach_shadow_of_class(space, TheClass) elif not isinstance(shadow, TheClass): shadow.detach_shadow() - shadow = self.attach_shadow_of_class(TheClass) + shadow = self.attach_shadow_of_class(space, TheClass) shadow.sync_shadow() return shadow - def get_shadow(self): + def get_shadow(self, space): from pypy.lang.smalltalk.shadow import AbstractShadow - return self.as_special_get_shadow(AbstractShadow) + return self.as_special_get_shadow(space, AbstractShadow) - def as_class_get_shadow(self): + def as_class_get_shadow(self, space): from pypy.lang.smalltalk.shadow import ClassShadow - return self.as_special_get_shadow(ClassShadow) + return self.as_special_get_shadow(space, ClassShadow) - def as_blockcontext_get_shadow(self): + def as_blockcontext_get_shadow(self, space): from pypy.lang.smalltalk.shadow import BlockContextShadow - return self.as_special_get_shadow(BlockContextShadow) + return self.as_special_get_shadow(space, BlockContextShadow) - def as_methodcontext_get_shadow(self): + def as_methodcontext_get_shadow(self, space): from pypy.lang.smalltalk.shadow import MethodContextShadow - return self.as_special_get_shadow(MethodContextShadow) + return self.as_special_get_shadow(space, MethodContextShadow) - def as_context_get_shadow(self): + def as_context_get_shadow(self, space): from pypy.lang.smalltalk.shadow import ContextPartShadow # XXX TODO should figure out itself if its method or block context if self._shadow is None: - if ContextPartShadow.is_block_context(self): - return self.as_blockcontext_get_shadow() - return self.as_methodcontext_get_shadow() - return self.as_special_get_shadow(ContextPartShadow) + if ContextPartShadow.is_block_context(self, space): + return self.as_blockcontext_get_shadow(space) + return self.as_methodcontext_get_shadow(space) + return self.as_special_get_shadow(space, ContextPartShadow) - def as_methoddict_get_shadow(self): + def as_methoddict_get_shadow(self, space): from pypy.lang.smalltalk.shadow import MethodDictionaryShadow - return self.as_special_get_shadow(MethodDictionaryShadow) + return self.as_special_get_shadow(space, MethodDictionaryShadow) def become(self, w_other): if not isinstance(w_other, W_PointersObject): @@ -356,13 +357,11 @@ W_AbstractObjectWithClassReference.__init__(self, w_class) self.bytes = ['\x00'] * size - def at0(self, index0): - from pypy.lang.smalltalk import utility - return utility.wrap_int(ord(self.getchar(index0))) + def at0(self, space, index0): + return space.wrap_int(ord(self.getchar(index0))) - def atput0(self, index0, w_value): - from pypy.lang.smalltalk import utility - self.setchar(index0, chr(utility.unwrap_int(w_value))) + def atput0(self, space, index0, w_value): + self.setchar(index0, chr(space.unwrap_int(w_value))) def getchar(self, n0): return self.bytes[n0] @@ -401,13 +400,11 @@ W_AbstractObjectWithClassReference.__init__(self, w_class) self.words = [0] * size - def at0(self, index0): - from pypy.lang.smalltalk import utility - return utility.wrap_int(self.getword(index0)) + def at0(self, space, index0): + return space.wrap_int(self.getword(index0)) - def atput0(self, index0, w_value): - from pypy.lang.smalltalk import utility - self.setword(index0, utility.unwrap_int(w_value)) + def atput0(self, space, index0, w_value): + self.setword(index0, space.unwrap_int(w_value)) def getword(self, n): return self.words[n] @@ -457,13 +454,13 @@ # Last of the literals is an association with compiledin # as a class w_association = self.literals[-1] - association = wrapper.AssociationWrapper(w_association) + # XXX XXX XXX where to get a space from here + association = wrapper.AssociationWrapper(None, w_association) self.w_compiledin = association.value() return self.w_compiledin - def getclass(self): - from pypy.lang.smalltalk.classtable import w_CompiledMethod - return w_CompiledMethod + def getclass(self, space): + return space.w_CompiledMethod def getliteral(self, index): # We changed this part @@ -474,10 +471,11 @@ assert isinstance(w_literal, W_BytesObject) return w_literal.as_string() # XXX performance issue here - def create_frame(self, receiver, arguments, sender = None): - from pypy.lang.smalltalk import objtable, shadow + def create_frame(self, space, receiver, arguments, sender = None): + from pypy.lang.smalltalk import shadow assert len(arguments) == self.argsize - w_new = shadow.MethodContextShadow.make_context(self, receiver, arguments, sender) + w_new = shadow.MethodContextShadow.make_context( + space, self, receiver, arguments, sender) return w_new def __str__(self): @@ -541,17 +539,15 @@ self.w_compiledin = None self.islarge = islarge - def literalat0(self, index0): + def literalat0(self, space, index0): if index0 == 0: - from pypy.lang.smalltalk import utility - return utility.wrap_int(self.getheader()) + return space.wrap_int(self.getheader()) else: return self.literals[index0-1] - def literalatput0(self, index0, w_value): + def literalatput0(self, space, index0, w_value): if index0 == 0: - from pypy.lang.smalltalk import utility - header = utility.unwrap_int(w_value) + header = space.unwrap_int(w_value) self.setheader(header) else: self.literals[index0-1] = w_value @@ -559,10 +555,9 @@ def store(self, index0, w_v): self.atput0(index0, w_v) - def at0(self, index0): - from pypy.lang.smalltalk import utility + def at0(self, space, index0): if index0 <= self.getliteralsize(): - return self.literalat0(index0/constants.BYTES_PER_WORD) + return self.literalat0(space, index0 / constants.BYTES_PER_WORD) else: # From blue book: # The literal count indicates the size of the @@ -571,17 +566,16 @@ # CompiledMethod's bytecodes start. index0 = index0 - self.getliteralsize() - self.headersize() assert index0 < len(self.bytes) - return utility.wrap_int(ord(self.bytes[index0])) + return space.wrap_int(ord(self.bytes[index0])) - def atput0(self, index0, w_value): - from pypy.lang.smalltalk import utility + def atput0(self, space, index0, w_value): if index0 <= self.getliteralsize(): - self.literalatput0(index0/constants.BYTES_PER_WORD, w_value) + self.literalatput0(space, index0 / constants.BYTES_PER_WORD, w_value) else: # XXX use to-be-written unwrap_char index0 = index0 - self.getliteralsize() - self.headersize() assert index0 < len(self.bytes) - self.setchar(index0, chr(utility.unwrap_int(w_value))) + self.setchar(index0, chr(space.unwrap_int(w_value))) def setchar(self, index0, character): assert index0 >= 0 @@ -590,6 +584,7 @@ # Use black magic to create w_nil without running the constructor, # thus allowing it to be used even in the constructor of its own -# class. Note that we patch its class in objtable. +# class. Note that we patch its class in the space +# YYY there should be no global w_nil w_nil = instantiate(W_PointersObject) w_nil._vars = [] Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/primitives.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/primitives.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/primitives.py Sun May 25 16:09:07 2008 @@ -1,9 +1,7 @@ import inspect import math import operator -from pypy.lang.smalltalk import model, shadow, utility -from pypy.lang.smalltalk import classtable -from pypy.lang.smalltalk import objtable +from pypy.lang.smalltalk import model, shadow from pypy.lang.smalltalk import constants from pypy.lang.smalltalk.error import PrimitiveFailedError, \ PrimitiveNotYetWrittenError @@ -15,8 +13,8 @@ if not minimum <= n0 < maximum: raise PrimitiveFailedError() -def assert_valid_index(n0, w_obj): - if not 0 <= n0 < w_obj.primsize(): +def assert_valid_index(space, n0, w_obj): + if not 0 <= n0 < w_obj.primsize(space): raise PrimitiveFailedError() # return the index, since from here on the annotator knows that # n0 cannot be negative @@ -79,7 +77,7 @@ def wrapped(interp, argument_count_m1): argument_count = argument_count_m1 + 1 # to account for the rcvr frame = interp.w_active_context() - s_frame = frame.as_context_get_shadow() + s_frame = frame.as_context_get_shadow(interp.space) assert argument_count == len_unwrap_spec if len(s_frame.stack()) < len_unwrap_spec: raise PrimitiveFailedError() @@ -88,11 +86,11 @@ index = len_unwrap_spec - 1 - i w_arg = s_frame.peek(index) if spec is int: - args += (utility.unwrap_int(w_arg), ) + args += (interp.space.unwrap_int(w_arg), ) elif spec is index1_0: - args += (utility.unwrap_int(w_arg)-1, ) + args += (interp.space.unwrap_int(w_arg)-1, ) elif spec is float: - args += (utility.unwrap_float(w_arg), ) + args += (interp.space.unwrap_float(w_arg), ) elif spec is object: args += (w_arg, ) elif spec is str: @@ -107,7 +105,7 @@ # After calling primitive, reload context-shadow in case it # needs to be updated new_s_frame = interp.s_active_context() - frame.as_context_get_shadow().pop_n(len_unwrap_spec) # only if no exception occurs! + frame.as_context_get_shadow(interp.space).pop_n(len_unwrap_spec) # only if no exception occurs! if not no_result: assert w_result is not None new_s_frame.push(w_result) @@ -146,7 +144,7 @@ res = rarithmetic.ovfcheck(op(receiver, argument)) except OverflowError: raise PrimitiveFailedError() - return utility.wrap_int(res) + return interp.space.wrap_int(res) make_func(op) bitwise_binary_ops = { @@ -159,7 +157,7 @@ @expose_primitive(code, unwrap_spec=[int, int]) def func(interp, receiver, argument): res = op(receiver, argument) - return utility.wrap_int(res) + return interp.space.wrap_int(res) make_func(op) # #/ -- return the result of a division, only succeed if the division is exact @@ -169,28 +167,28 @@ raise PrimitiveFailedError() if receiver % argument != 0: raise PrimitiveFailedError() - return utility.wrap_int(receiver // argument) + return interp.space.wrap_int(receiver // argument) # #\\ -- return the remainder of a division @expose_primitive(MOD, unwrap_spec=[int, int]) def func(interp, receiver, argument): if argument == 0: raise PrimitiveFailedError() - return utility.wrap_int(receiver % argument) + return interp.space.wrap_int(receiver % argument) # #// -- return the result of a division, rounded towards negative zero @expose_primitive(DIV, unwrap_spec=[int, int]) def func(interp, receiver, argument): if argument == 0: raise PrimitiveFailedError() - return utility.wrap_int(receiver // argument) + return interp.space.wrap_int(receiver // argument) # #// -- return the result of a division, rounded towards negative infinity @expose_primitive(QUO, unwrap_spec=[int, int]) def func(interp, receiver, argument): if argument == 0: raise PrimitiveFailedError() - return utility.wrap_int(receiver // argument) + return interp.space.wrap_int(receiver // argument) # #bitShift: -- return the shifted value @expose_primitive(BIT_SHIFT, unwrap_spec=[int, int]) @@ -201,11 +199,11 @@ shifted = receiver << argument if (shifted >> argument) != receiver: raise PrimitiveFailedError() - return utility.wrap_int(shifted) + return interp.space.wrap_int(shifted) # right shift, ok to lose bits else: - return utility.wrap_int(receiver >> -argument) + return interp.space.wrap_int(receiver >> -argument) # ___________________________________________________________________________ @@ -236,35 +234,35 @@ def make_func(op): @expose_primitive(code, unwrap_spec=[float, float]) def func(interp, v1, v2): - w_res = utility.wrap_float(op(v1, v2)) + w_res = interp.space.wrap_float(op(v1, v2)) return w_res make_func(op) @expose_primitive(FLOAT_TRUNCATED, unwrap_spec=[float]) def func(interp, f): - w_res = utility.wrap_int(int(f)) + w_res = interp.space.wrap_int(int(f)) return w_res @expose_primitive(FLOAT_TIMES_TWO_POWER, unwrap_spec=[float, int]) def func(interp, rcvr, arg): - w_res = utility.wrap_float(math.ldexp(rcvr, arg)) + w_res = interp.space.wrap_float(math.ldexp(rcvr, arg)) return w_res @expose_primitive(FLOAT_SQUARE_ROOT, unwrap_spec=[float]) def func(interp, f): if f < 0.0: raise PrimitiveFailedError - w_res = utility.wrap_float(math.sqrt(f)) + w_res = interp.space.wrap_float(math.sqrt(f)) return w_res @expose_primitive(FLOAT_SIN, unwrap_spec=[float]) def func(interp, f): - w_res = utility.wrap_float(math.sin(f)) + w_res = interp.space.wrap_float(math.sin(f)) return w_res @expose_primitive(FLOAT_ARCTAN, unwrap_spec=[float]) def func(interp, f): - w_res = utility.wrap_float(math.atan(f)) + w_res = interp.space.wrap_float(math.atan(f)) return w_res @expose_primitive(FLOAT_LOG_N, unwrap_spec=[float]) @@ -275,11 +273,11 @@ res = rarithmetic.NAN else: res = math.log(f) - return utility.wrap_float(res) + return interp.space.wrap_float(res) @expose_primitive(FLOAT_EXP, unwrap_spec=[float]) def func(interp, f): - w_res = utility.wrap_float(math.exp(f)) + w_res = interp.space.wrap_float(math.exp(f)) return w_res # ___________________________________________________________________________ @@ -298,34 +296,34 @@ @expose_primitive(AT, unwrap_spec=[object, index1_0]) def func(interp, w_obj, n0): - n0 = assert_valid_index(n0, w_obj) - return w_obj.at0(n0) + n0 = assert_valid_index(interp.space, n0, w_obj) + return w_obj.at0(interp.space, n0) @expose_primitive(AT_PUT, unwrap_spec=[object, index1_0, object]) def func(interp, w_obj, n0, w_val): - n0 = assert_valid_index(n0, w_obj) - w_obj.atput0(n0, w_val) + n0 = assert_valid_index(interp.space, n0, w_obj) + w_obj.atput0(interp.space, n0, w_val) return w_val @expose_primitive(SIZE, unwrap_spec=[object]) def func(interp, w_obj): - if not w_obj.shadow_of_my_class().isvariable(): + if not w_obj.shadow_of_my_class(interp.space).isvariable(): raise PrimitiveFailedError() - return utility.wrap_int(w_obj.primsize()) + return interp.space.wrap_int(w_obj.primsize(interp.space)) @expose_primitive(STRING_AT, unwrap_spec=[object, index1_0]) def func(interp, w_obj, n0): - n0 = assert_valid_index(n0, w_obj) + n0 = assert_valid_index(interp.space, n0, w_obj) # XXX I am not sure this is correct, but it un-breaks translation: # make sure that getbyte is only performed on W_BytesObjects if not isinstance(w_obj, model.W_BytesObject): raise PrimitiveFailedError - return utility.wrap_char(w_obj.getchar(n0)) + return interp.space.wrap_char(w_obj.getchar(n0)) @expose_primitive(STRING_AT_PUT, unwrap_spec=[object, index1_0, object]) def func(interp, w_obj, n0, w_val): - val = utility.unwrap_char(w_val) - n0 = assert_valid_index(n0, w_obj) + val = interp.space.unwrap_char(w_val) + n0 = assert_valid_index(interp.space, n0, w_obj) if not (isinstance(w_obj, model.W_CompiledMethod) or isinstance(w_obj, model.W_BytesObject)): raise PrimitiveFailedError() @@ -359,20 +357,20 @@ def func(interp, w_rcvr, n0): if not isinstance(w_rcvr, model.W_CompiledMethod): raise PrimitiveFailedError() - return w_rcvr.literalat0(n0) + return w_rcvr.literalat0(interp.space, n0) @expose_primitive(OBJECT_AT_PUT, unwrap_spec=[object, index1_0, object]) def func(interp, w_rcvr, n0, w_value): if not isinstance(w_rcvr, model.W_CompiledMethod): raise PrimitiveFailedError() #assert_bounds(n0, 0, len(w_rcvr.literals)) - w_rcvr.literalatput0(n0, w_value) + w_rcvr.literalatput0(interp.space, n0, w_value) return w_value @expose_primitive(NEW, unwrap_spec=[object]) def func(interp, w_cls): assert isinstance(w_cls, model.W_PointersObject) - s_class = w_cls.as_class_get_shadow() + s_class = w_cls.as_class_get_shadow(interp.space) if s_class.isvariable(): raise PrimitiveFailedError() return s_class.new() @@ -380,7 +378,7 @@ @expose_primitive(NEW_WITH_ARG, unwrap_spec=[object, int]) def func(interp, w_cls, size): assert isinstance(w_cls, model.W_PointersObject) - s_class = w_cls.as_class_get_shadow() + s_class = w_cls.as_class_get_shadow(interp.space) if not s_class.isvariable(): raise PrimitiveFailedError() return s_class.new(size) @@ -392,7 +390,7 @@ @expose_primitive(INST_VAR_AT, unwrap_spec=[object, index1_0]) def func(interp, w_rcvr, n0): "Fetches a fixed field from the object, and fails otherwise" - s_class = w_rcvr.shadow_of_my_class() + s_class = w_rcvr.shadow_of_my_class(interp.space) assert_bounds(n0, 0, s_class.instsize()) # only pointers have non-0 size # XXX Now MethodContext is still own format, leave @@ -402,7 +400,7 @@ @expose_primitive(INST_VAR_AT_PUT, unwrap_spec=[object, index1_0, object]) def func(interp, w_rcvr, n0, w_value): "Stores a value into a fixed field from the object, and fails otherwise" - s_class = w_rcvr.shadow_of_my_class() + s_class = w_rcvr.shadow_of_my_class(interp.space) assert_bounds(n0, 0, s_class.instsize()) # XXX Now MethodContext is still own format, leave #assert isinstance(w_rcvr, model.W_PointersObject) @@ -413,7 +411,7 @@ def func(interp, w_rcvr): if isinstance(w_rcvr, model.W_SmallInteger): raise PrimitiveFailedError() - return utility.wrap_int(w_rcvr.gethash()) + return interp.space.wrap_int(w_rcvr.gethash()) @expose_primitive(STORE_STACKP, unwrap_spec=[object, object]) def func(interp, w_obj1, w_obj2): @@ -452,11 +450,11 @@ @expose_primitive(EQUIVALENT, unwrap_spec=[object, object]) def func(interp, w_arg, w_rcvr): - return utility.wrap_bool(w_arg.is_same_object(w_rcvr)) + return interp.space.wrap_bool(w_arg.is_same_object(w_rcvr)) @expose_primitive(CLASS, unwrap_spec=[object]) def func(interp, w_obj): - return w_obj.getclass() + return w_obj.getclass(interp.space) @expose_primitive(BYTES_LEFT, unwrap_spec=[object]) def func(interp, w_rcvr): @@ -472,15 +470,15 @@ @expose_primitive(CHANGE_CLASS, unwrap_spec=[object, object], no_result=True) def func(interp, w_arg, w_rcvr): - w_arg_class = w_arg.getclass() - w_rcvr_class = w_rcvr.getclass() + w_arg_class = w_arg.getclass(interp.space) + w_rcvr_class = w_rcvr.getclass(interp.space) # We should fail if: # 1. Rcvr or arg are SmallIntegers # XXX this is wrong too - if (w_arg_class.is_same_object(classtable.w_SmallInteger) or - w_rcvr_class.is_same_object(classtable.w_SmallInteger)): + if (w_arg_class.is_same_object(interp.space.w_SmallInteger) or + w_rcvr_class.is_same_object(interp.space.w_SmallInteger)): raise PrimitiveFailedError() # 2. Rcvr is an instance of a compact class and argument isn't @@ -510,15 +508,15 @@ return w_rcvr raise PrimitiveFailedError -def fake_bytes_left(): - return utility.wrap_int(2**20) # XXX we don't know how to do this :-( +def fake_bytes_left(interp): + return interp.space.wrap_int(2**20) # XXX we don't know how to do this :-( @expose_primitive(INC_GC, unwrap_spec=[object]) @expose_primitive(FULL_GC, unwrap_spec=[object]) def func(interp, w_arg): # Squeak pops the arg and ignores it ... go figure from pypy.rlib import rgc rgc.collect() - return fake_bytes_left() + return fake_bytes_left(interp) #____________________________________________________________________________ # Time Primitives @@ -529,13 +527,13 @@ def func(interp, w_arg): import time import math - return utility.wrap_int(int(math.fmod(time.time()*1000, constants.TAGGED_MAXINT/2))) + return interp.space.wrap_int(int(math.fmod(time.time()*1000, constants.TAGGED_MAXINT/2))) @expose_primitive(SECONDS_CLOCK, unwrap_spec=[object]) def func(interp, w_arg): import time - return utility.wrap_int(0x23910d6c) # HACK: too big for a small int! - #return utility.wrap_int(int(time.time())) + return interp.space.wrap_int(0x23910d6c) # HACK: too big for a small int! + #return interp.space.wrap_int(int(time.time())) # ___________________________________________________________________________ # Boolean Primitives @@ -567,7 +565,7 @@ @expose_primitive(code, unwrap_spec=[int, int]) def func(interp, v1, v2): res = op(v1, v2) - w_res = utility.wrap_bool(res) + w_res = interp.space.wrap_bool(res) return w_res make_func(op) @@ -576,7 +574,7 @@ @expose_primitive(code+_FLOAT_OFFSET, unwrap_spec=[float, float]) def func(interp, v1, v2): res = op(v1, v2) - w_res = utility.wrap_bool(res) + w_res = interp.space.wrap_bool(res) return w_res make_func(op) @@ -597,20 +595,21 @@ # no-op really return w_self -for (code, const) in [ - (PUSH_TRUE, objtable.w_true), - (PUSH_FALSE, objtable.w_false), - (PUSH_NIL, objtable.w_nil), - (PUSH_MINUS_ONE, objtable.w_minus_one), - (PUSH_ZERO, objtable.w_zero), - (PUSH_ONE, objtable.w_one), - (PUSH_TWO, objtable.w_two), +def make_push_const_func(code, name): + @expose_primitive(code, unwrap_spec=[object]) + def func(interp, w_ignored): + return getattr(interp.space, name) + +for (code, name) in [ + (PUSH_TRUE, "w_true"), + (PUSH_FALSE, "w_false"), + (PUSH_NIL, "w_nil"), + (PUSH_MINUS_ONE, "w_minus_one"), + (PUSH_ZERO, "w_zero"), + (PUSH_ONE, "w_one"), + (PUSH_TWO, "w_two"), ]: - def make_func(const): - @expose_primitive(code, unwrap_spec=[object]) - def func(interp, w_ignored): - return const - make_func(const) + make_push_const_func(code, name) # ___________________________________________________________________________ # Control Primitives @@ -635,13 +634,14 @@ # context of the receiver is used for the new BlockContext. # Note that in our impl, MethodContext.w_home == self assert isinstance(w_context, model.W_PointersObject) - w_method_context = w_context.as_context_get_shadow().w_home() + w_method_context = w_context.as_context_get_shadow(interp.space).w_home() # The block bytecodes are stored inline: so we skip past the # byteodes to invoke this primitive to find them (hence +2) initialip = frame.pc() + 2 w_new_context = shadow.BlockContextShadow.make_context( - w_method_context, objtable.w_nil, argcnt, initialip) + interp.space, + w_method_context, interp.space.w_nil, argcnt, initialip) return w_new_context def finalize_block_ctx(interp, s_block_ctx, frame): @@ -665,12 +665,13 @@ w_block_ctx = frame.peek(argument_count) # XXX need to check this since VALUE is called on all sorts of objects. - if not w_block_ctx.getclass().is_same_object(classtable.w_BlockContext): + if not w_block_ctx.getclass(interp.space).is_same_object( + interp.space.w_BlockContext): raise PrimitiveFailedError() assert isinstance(w_block_ctx, model.W_PointersObject) - s_block_ctx = w_block_ctx.as_blockcontext_get_shadow() + s_block_ctx = w_block_ctx.as_blockcontext_get_shadow(interp.space) exp_arg_cnt = s_block_ctx.expected_argument_count() if argument_count != exp_arg_cnt: # exp_arg_cnt doesn't count self @@ -692,11 +693,12 @@ def func(interp, w_block_ctx, w_args): assert isinstance(w_block_ctx, model.W_PointersObject) - s_block_ctx = w_block_ctx.as_blockcontext_get_shadow() + s_block_ctx = w_block_ctx.as_blockcontext_get_shadow(interp.space) exp_arg_cnt = s_block_ctx.expected_argument_count() # Check that our arguments have pointers format and the right size: - if not w_args.getclass().is_same_object(classtable.w_Array): + if not w_args.getclass(interp.space).is_same_object( + interp.space.w_Array): raise PrimitiveFailedError() if w_args.size() != exp_arg_cnt: raise PrimitiveFailedError() @@ -704,7 +706,7 @@ assert isinstance(w_args, model.W_PointersObject) # Push all the items from the array for i in range(exp_arg_cnt): - s_block_ctx.push(w_args.at0(i)) + s_block_ctx.push(w_args.at0(interp.space, i)) # XXX Check original logic. Image does not test this anyway # because falls back to value + internal implementation @@ -718,45 +720,49 @@ unwrap_spec=[object, str, object], no_result=True) def func(interp, w_rcvr, sel, w_args): - w_method = w_rcvr.shadow_of_my_class().lookup(sel) + w_method = w_rcvr.shadow_of_my_class(interp.space).lookup(sel) assert w_method - w_frame = w_method.create_frame(w_rcvr, + w_frame = w_method.create_frame(interp.space, w_rcvr, [w_args.fetch(i) for i in range(w_args.size())]) - w_frame.as_context_get_shadow().store_w_sender(interp.w_active_context()) + w_frame.as_context_get_shadow(interp.space).store_w_sender(interp.w_active_context()) interp.store_w_active_context(w_frame) @expose_primitive(PRIMITIVE_SIGNAL, unwrap_spec=[object]) def func(interp, w_rcvr): # XXX we might want to disable this check - if not w_rcvr.getclass().is_same_object(classtable.classtable['w_Semaphore']): + if not w_rcvr.getclass(interp.space).is_same_object( + interp.space.classtable['w_Semaphore']): raise PrimitiveFailedError() - wrapper.SemaphoreWrapper(w_rcvr).signal(interp) + wrapper.SemaphoreWrapper(interp.space, w_rcvr).signal(interp) return w_rcvr @expose_primitive(PRIMITIVE_WAIT, unwrap_spec=[object]) def func(interp, w_rcvr): # XXX we might want to disable this check - if not w_rcvr.getclass().is_same_object(classtable.classtable['w_Semaphore']): + if not w_rcvr.getclass(interp.space).is_same_object( + interp.space.classtable['w_Semaphore']): raise PrimitiveFailedError() - wrapper.SemaphoreWrapper(w_rcvr).wait(interp) + wrapper.SemaphoreWrapper(interp.space, w_rcvr).wait(interp) return w_rcvr @expose_primitive(PRIMITIVE_RESUME, unwrap_spec=[object]) def func(interp, w_rcvr,): # XXX we might want to disable this check - if not w_rcvr.getclass().is_same_object(classtable.classtable['w_Process']): + if not w_rcvr.getclass(interp.space).is_same_object( + interp.space.classtable['w_Process']): raise PrimitiveFailedError() - wrapper.ProcessWrapper(w_rcvr).resume(interp) + wrapper.ProcessWrapper(interp.space, w_rcvr).resume(interp) return w_rcvr @expose_primitive(PRIMITIVE_SUSPEND, unwrap_spec=[object]) def func(interp, w_rcvr): # XXX we might want to disable this check - if not w_rcvr.getclass().is_same_object(classtable.classtable['w_Process']): + if not w_rcvr.getclass(interp.space).is_same_object( + interp.space.classtable['w_Process']): raise PrimitiveFailedError() - wrapper.ProcessWrapper(w_rcvr).suspend(interp) + wrapper.ProcessWrapper(interp.space, w_rcvr).suspend(interp) return w_rcvr @expose_primitive(PRIMITIVE_FLUSH_CACHE, unwrap_spec=[object]) Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py Sun May 25 16:09:07 2008 @@ -1,12 +1,13 @@ import weakref -from pypy.lang.smalltalk import model, constants, utility, error +from pypy.lang.smalltalk import model, constants, error from pypy.tool.pairtype import extendabletype class AbstractShadow(object): """A shadow is an optional extra bit of information that can be attached at run-time to any Smalltalk object. """ - def __init__(self, w_self): + def __init__(self, space, w_self): + self.space = space self._w_self = w_self def fetch(self, n0): return self.w_self()._fetch(n0) @@ -23,8 +24,8 @@ def sync_shadow(self): pass class AbstractCachingShadow(AbstractShadow): - def __init__(self, w_self): - AbstractShadow.__init__(self, w_self) + def __init__(self, space, w_self): + AbstractShadow.__init__(self, space, w_self) self.invalid = True self.invalidate_shadow() @@ -75,9 +76,9 @@ """A shadow for Smalltalk objects that are classes (i.e. used as the class of another Smalltalk object). """ - def __init__(self, w_self): + def __init__(self, space, w_self): self.name = "" - AbstractCachingShadow.__init__(self, w_self) + AbstractCachingShadow.__init__(self, space, w_self) def invalidate_shadow(self): AbstractCachingShadow.invalidate_shadow(self) self.w_methoddict = None @@ -87,12 +88,11 @@ return "%s class" % (self.name or '?',) def sync_cache(self): - from pypy.lang.smalltalk.objtable import w_nil "Update the ClassShadow with data from the w_self class." w_self = self.w_self() # read and painfully decode the format - classformat = utility.unwrap_int( + classformat = self.space.unwrap_int( w_self._fetch(constants.CLASS_FORMAT_INDEX)) # The classformat in Squeak, as an integer value, is: # <2 bits=instSize//64><5 bits=cClass><4 bits=instSpec> @@ -135,7 +135,7 @@ self.w_methoddict = w_methoddict w_superclass = w_self._fetch(constants.CLASS_SUPERCLASS_INDEX) - if w_superclass.is_same_object(w_nil): + if w_superclass.is_same_object(self.space.w_nil): self.w_superclass = None else: assert isinstance(w_superclass, model.W_PointersObject) @@ -166,7 +166,6 @@ self.name = w_name.as_string() def new(self, extrasize=0): - from pypy.lang.smalltalk import classtable w_cls = self.w_self() if self.instance_kind == POINTERS: w_new = model.W_PointersObject(w_cls, self.instance_size+extrasize) @@ -181,12 +180,12 @@ return w_new def s_methoddict(self): - return self.w_methoddict.as_methoddict_get_shadow() + return self.w_methoddict.as_methoddict_get_shadow(self.space) def s_superclass(self): if self.w_superclass is None: return None - return self.w_superclass.as_class_get_shadow() + return self.w_superclass.as_class_get_shadow(self.space) # _______________________________________________________________ # Methods for querying the format word, taken from the blue book: @@ -262,17 +261,16 @@ self.methoddict = None def sync_cache(self): - from pypy.lang.smalltalk import objtable w_values = self.w_self()._fetch(constants.METHODDICT_VALUES_INDEX) assert isinstance(w_values, model.W_PointersObject) - s_values = w_values.get_shadow() + s_values = w_values.get_shadow(self.space) # XXX Should add! # s_values.notifyinvalid(self) size = self.w_self().size() - constants.METHODDICT_NAMES_INDEX self.methoddict = {} for i in range(size): w_selector = self.w_self()._fetch(constants.METHODDICT_NAMES_INDEX+i) - if not w_selector.is_same_object(objtable.w_nil): + if not w_selector.is_same_object(self.space.w_nil): if not isinstance(w_selector, model.W_BytesObject): raise ClassShadowError("bogus selector in method dict") selector = w_selector.as_string() @@ -284,8 +282,8 @@ class AbstractRedirectingShadow(AbstractShadow): - def __init__(self, w_self): - AbstractShadow.__init__(self, w_self) + def __init__(self, space, w_self): + AbstractShadow.__init__(self, space, w_self) self._w_self_size = self.w_self().size() def fetch(self, n0): raise NotImplementedError() @@ -301,8 +299,7 @@ self.w_self()._vars = None def detach_shadow(self): - from pypy.lang.smalltalk import objtable - self.w_self()._vars = [objtable.w_nil] * self._w_self_size + self.w_self()._vars = [self.space.w_nil] * self._w_self_size for i in range(self._w_self_size): self.copy_to_w_self(i) @@ -315,18 +312,17 @@ __metaclass__ = extendabletype - def __init__(self, w_self): - from pypy.lang.smalltalk import objtable - self._w_sender = objtable.w_nil + def __init__(self, space, w_self): + self._w_sender = space.w_nil self._stack = [] self.currentBytecode = -1 - AbstractRedirectingShadow.__init__(self, w_self) + AbstractRedirectingShadow.__init__(self, space, w_self) @staticmethod - def is_block_context(w_pointers): - from pypy.lang.smalltalk.classtable import w_SmallInteger + def is_block_context(w_pointers, space): method_or_argc = w_pointers.fetch(constants.MTHDCTX_METHOD) - return method_or_argc.getclass().is_same_object(w_SmallInteger) + return method_or_argc.getclass(space).is_same_object( + space.w_SmallInteger) def fetch(self, n0): if n0 == constants.CTXPART_SENDER_INDEX: @@ -338,8 +334,7 @@ if self.stackstart() <= n0 < self.external_stackpointer(): return self._stack[n0-self.stackstart()] if self.external_stackpointer() <= n0 < self.stackend(): - from pypy.lang.smalltalk import objtable - return objtable.w_nil + return self.space.w_nil else: # XXX later should store tail out of known context part as well raise error.WrapperException("Index in context out of bounds") @@ -364,21 +359,20 @@ # the stackpointer in the W_PointersObject starts counting at the # tempframe start # Stackpointer from smalltalk world == stacksize in python world - self.store_stackpointer(utility.unwrap_int(w_sp1) - + self.store_stackpointer(self.space.unwrap_int(w_sp1) - self.tempsize()) def store_stackpointer(self, size): - from pypy.lang.smalltalk import objtable if size < len(self._stack): # TODO Warn back to user assert size >= 0 self._stack = self._stack[:size] else: - add = [objtable.w_nil] * (size - len(self._stack)) + add = [self.space.w_nil] * (size - len(self._stack)) self._stack.extend(add) def wrap_stackpointer(self): - return utility.wrap_int(len(self._stack) + + return self.space.wrap_int(len(self._stack) + self.tempsize()) def external_stackpointer(self): @@ -388,7 +382,7 @@ raise NotImplementedError() def s_home(self): - return self.w_home().as_methodcontext_get_shadow() + return self.w_home().as_methodcontext_get_shadow(self.space) def stackstart(self): raise NotImplementedError() @@ -408,18 +402,16 @@ return self._w_sender def s_sender(self): - from pypy.lang.smalltalk import objtable w_sender = self.w_sender() - if w_sender.is_same_object(objtable.w_nil): + if w_sender.is_same_object(self.space.w_nil): return None else: - return w_sender.as_context_get_shadow() + return w_sender.as_context_get_shadow(self.space) def store_unwrap_pc(self, w_pc): - from pypy.lang.smalltalk import objtable - if w_pc.is_same_object(objtable.w_nil): + if w_pc.is_same_object(self.space.w_nil): return - pc = utility.unwrap_int(w_pc) + pc = self.space.unwrap_int(w_pc) pc -= self.w_method().bytecodeoffset() pc -= 1 self.store_pc(pc) @@ -428,7 +420,7 @@ pc = self.pc() pc += 1 pc += self.w_method().bytecodeoffset() - return utility.wrap_int(pc) + return self.space.wrap_int(pc) def pc(self): return self._pc @@ -511,14 +503,13 @@ class BlockContextShadow(ContextPartShadow): @staticmethod - def make_context(w_home, w_sender, argcnt, initialip): - from pypy.lang.smalltalk.classtable import w_BlockContext + def make_context(space, w_home, w_sender, argcnt, initialip): # create and attach a shadow manually, to not have to carefully put things # into the right places in the W_PointersObject # XXX could hack some more to never have to create the _vars of w_result - contextsize = w_home.as_methodcontext_get_shadow().myblocksize() - w_result = model.W_PointersObject(w_BlockContext, contextsize) - s_result = BlockContextShadow(w_result) + contextsize = w_home.as_methodcontext_get_shadow(space).myblocksize() + w_result = model.W_PointersObject(space.w_BlockContext, contextsize) + s_result = BlockContextShadow(space, w_result) w_result.store_shadow(s_result) s_result.store_expected_argument_count(argcnt) s_result.store_initialip(initialip) @@ -552,20 +543,20 @@ ContextPartShadow.attach_shadow(self) def unwrap_store_initialip(self, w_value): - initialip = utility.unwrap_int(w_value) + initialip = self.space.unwrap_int(w_value) initialip -= 1 + self.w_method().getliteralsize() self.store_initialip(initialip) def wrap_initialip(self): initialip = self.initialip() initialip += 1 + self.w_method().getliteralsize() - return utility.wrap_int(initialip) + return self.space.wrap_int(initialip) def unwrap_store_eargc(self, w_value): - self.store_expected_argument_count(utility.unwrap_int(w_value)) + self.store_expected_argument_count(self.space.unwrap_int(w_value)) def wrap_eargc(self): - return utility.wrap_int(self.expected_argument_count()) + return self.space.wrap_int(self.expected_argument_count()) def expected_argument_count(self): return self._eargc @@ -600,33 +591,30 @@ return 0 class MethodContextShadow(ContextPartShadow): - def __init__(self, w_self): - from pypy.lang.smalltalk import objtable - self.w_receiver_map = objtable.w_nil + def __init__(self, space, w_self): + self.w_receiver_map = space.w_nil self._w_receiver = None - ContextPartShadow.__init__(self, w_self) + ContextPartShadow.__init__(self, space, w_self) @staticmethod - def make_context(w_method, w_receiver, + def make_context(space, w_method, w_receiver, arguments, w_sender=None): - from pypy.lang.smalltalk.classtable import w_MethodContext - from pypy.lang.smalltalk import objtable # From blue book: normal mc have place for 12 temps+maxstack # mc for methods with islarge flag turned on 32 size = 12 + w_method.islarge * 20 + w_method.argsize - w_result = w_MethodContext.as_class_get_shadow().new(size) + w_result = space.w_MethodContext.as_class_get_shadow(space).new(size) assert isinstance(w_result, model.W_PointersObject) # create and attach a shadow manually, to not have to carefully put things # into the right places in the W_PointersObject # XXX could hack some more to never have to create the _vars of w_result - s_result = MethodContextShadow(w_result) + s_result = MethodContextShadow(space, w_result) w_result.store_shadow(s_result) s_result.store_w_method(w_method) if w_sender: s_result.store_w_sender(w_sender) s_result.store_w_receiver(w_receiver) s_result.store_pc(0) - s_result._temps = [objtable.w_nil] * w_method.tempsize + s_result._temps = [space.w_nil] * w_method.tempsize for i in range(len(arguments)): s_result.settemp(i, arguments[i]) return w_result @@ -661,11 +649,10 @@ return ContextPartShadow.store(self, n0, w_value) def attach_shadow(self): - from pypy.lang.smalltalk import objtable # Make sure the method is updated first self.copy_from_w_self(constants.MTHDCTX_METHOD) # And that there is space for the temps - self._temps = [objtable.w_nil] * self.tempsize() + self._temps = [self.space.w_nil] * self.tempsize() ContextPartShadow.attach_shadow(self) def tempsize(self): Added: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/space.py ============================================================================== --- (empty file) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/space.py Sun May 25 16:09:07 2008 @@ -0,0 +1,236 @@ +from pypy.lang.smalltalk import constants +from pypy.lang.smalltalk import model +from pypy.lang.smalltalk import shadow +from pypy.rlib.objectmodel import instantiate +from pypy.lang.smalltalk.error import UnwrappingError, WrappingError + +class ObjSpace(object): + def __init__(self): + self.classtable = {} + self.make_bootstrap_classes() + self.make_bootstrap_objects() + + def make_bootstrap_classes(self): + def define_core_cls(name, w_superclass, w_metaclass): + assert name.startswith('w_') + w_class = bootstrap_class(self, instsize=0, # XXX + w_superclass=w_superclass, + w_metaclass=w_metaclass, + name=name[2:]) + self.classtable[name] = w_class + return w_class + + # A complete minimal setup (including Behavior) would look like this + # + # class: superclass: metaclass: + # ------------------- ------------------- ------------------- + # Object *nil Object class + # Behavior Object Behavior class + # ClassDescription Behavior ClassDescription class + # Class ClassDescription Class class + # Metaclass ClassDescription Metaclass class + # Object class *Class *Metaclass + # Behavior class Object class *Metaclass + # ClassDescription cl Behavior class *Metaclass + # Class class ClassDescription cl *Metaclass + # Metaclass class ClassDescription cl *Metaclass + + # Class Name Super class name + cls_nm_tbl = [ + ["w_Object", "w_ProtoObject"], # there is not ProtoObject in mini.image + ["w_Behavior", "w_Object"], + ["w_ClassDescription", "w_Behavior"], + ["w_Class", "w_ClassDescription"], + ["w_Metaclass", "w_ClassDescription"], + ] + define_core_cls("w_ProtoObjectClass", None, None) + w_ProtoObjectClass = self.classtable["w_ProtoObjectClass"] + define_core_cls("w_ProtoObject", None, w_ProtoObjectClass) + for (cls_nm, super_cls_nm) in cls_nm_tbl: + meta_nm = cls_nm + "Class" + meta_super_nm = super_cls_nm + "Class" + w_metacls = define_core_cls(meta_nm, self.classtable[meta_super_nm], None) + define_core_cls(cls_nm, self.classtable[super_cls_nm], w_metacls) + w_Class = self.classtable["w_Class"] + w_Metaclass = self.classtable["w_Metaclass"] + # XXX + proto_shadow = instantiate(shadow.ClassShadow) + proto_shadow.space = self + proto_shadow.invalid = False + proto_shadow.w_superclass = w_Class + w_ProtoObjectClass.store_shadow(proto_shadow) + # at this point, all classes that still lack a w_class are themselves + # metaclasses + for nm, w_cls_obj in self.classtable.items(): + if w_cls_obj.w_class is None: + w_cls_obj.w_class = w_Metaclass + + def define_cls(cls_nm, supercls_nm, instvarsize=0, format=shadow.POINTERS, + varsized=False): + assert cls_nm.startswith("w_") + meta_nm = cls_nm + "Class" + meta_super_nm = supercls_nm + "Class" + w_Metaclass = self.classtable["w_Metaclass"] + w_meta_cls = self.classtable[meta_nm] = \ + bootstrap_class(self, 0, # XXX + self.classtable[meta_super_nm], + w_Metaclass, + name=meta_nm[2:]) + w_cls = self.classtable[cls_nm] = \ + bootstrap_class(self, instvarsize, + self.classtable[supercls_nm], + w_meta_cls, + format=format, + varsized=varsized, + name=cls_nm[2:]) + + define_cls("w_Magnitude", "w_Object") + define_cls("w_Character", "w_Magnitude", instvarsize=1) + define_cls("w_Number", "w_Magnitude") + define_cls("w_Integer", "w_Number") + define_cls("w_SmallInteger", "w_Integer") + define_cls("w_Float", "w_Number", format=shadow.BYTES) + define_cls("w_Collection", "w_Object") + define_cls("w_SequenceableCollection", "w_Collection") + define_cls("w_ArrayedCollection", "w_SequenceableCollection") + define_cls("w_Array", "w_ArrayedCollection", varsized=True) + define_cls("w_String", "w_ArrayedCollection", format=shadow.BYTES) + define_cls("w_UndefinedObject", "w_Object") + define_cls("w_Boolean", "w_Object") + define_cls("w_True", "w_Boolean") + define_cls("w_False", "w_Boolean") + define_cls("w_ByteArray", "w_ArrayedCollection", format=shadow.BYTES) + define_cls("w_MethodDict", "w_Object", instvarsize=2, varsized=True) + define_cls("w_CompiledMethod", "w_ByteArray", format=shadow.COMPILED_METHOD) + define_cls("w_ContextPart", "w_Object") + define_cls("w_MethodContext", "w_ContextPart") + define_cls("w_Link", "w_Object") + define_cls("w_Process", "w_Link") + define_cls("w_LinkedList", "w_SequenceableCollection") + define_cls("w_Semaphore", "w_LinkedList") + define_cls("w_BlockContext", "w_ContextPart", + instvarsize=constants.BLKCTX_STACK_START) + + # make better accessors for classes that can be found in special object + # table + for name in constants.classes_in_special_object_table.keys(): + name = 'w_' + name + setattr(self, name, self.classtable.get(name)) + + def make_bootstrap_objects(self): + def bld_char(i): + w_cinst = self.w_Character.as_class_get_shadow(self).new() + w_cinst.store(constants.CHARACTER_VALUE_INDEX, + model.W_SmallInteger(i)) + return w_cinst + w_charactertable = model.W_PointersObject( + self.classtable['w_Array'], 256) + self.w_charactertable = w_charactertable + for i in range(256): + self.w_charactertable.atput0(self, i, bld_char(i)) + + + # Very special nil hack: in order to allow W_PointersObject's to + # initialize their fields to nil, we have to create it in the model + # package, and then patch up its fields here: + w_nil = self.w_nil = model.w_nil + w_nil.w_class = self.classtable['w_UndefinedObject'] + + w_true = self.classtable['w_True'].as_class_get_shadow(self).new() + self.w_true = w_true + w_false = self.classtable['w_False'].as_class_get_shadow(self).new() + self.w_false = w_false + self.w_minus_one = model.W_SmallInteger(-1) + self.w_zero = model.W_SmallInteger(0) + self.w_one = model.W_SmallInteger(1) + self.w_two = model.W_SmallInteger(2) + self.objtable = {} + + for name in constants.objects_in_special_object_table: + name = "w_" + name + try: + self.objtable[name] = locals()[name] + except KeyError, e: + self.objtable[name] = None + + # methods for wrapping and unwrapping stuff + + def wrap_int(self, val): + from pypy.lang.smalltalk import constants + if constants.TAGGED_MININT <= val <= constants.TAGGED_MAXINT: + return model.W_SmallInteger(val) + raise WrappingError("integer too large to fit into a tagged pointer") + + def wrap_float(self, i): + return model.W_Float(i) + + def wrap_string(self, string): + w_inst = self.w_String.as_class_get_shadow(self).new(len(string)) + for i in range(len(string)): + w_inst.setchar(i, string[i]) + return w_inst + + def wrap_char(self, c): + return self.w_charactertable.fetch(ord(c)) + + def wrap_bool(self, b): + if b: + return self.w_true + else: + return self.w_false + + def wrap_list(self, lst_w): + """ + Converts a Python list of wrapper objects into + a wrapped smalltalk array + """ + lstlen = len(lst_w) + res = self.w_Array.as_class_get_shadow().new(lstlen) + for i in range(lstlen): + res.storevarpointer(i, lit[i]) + return res + + def unwrap_int(self, w_value): + if isinstance(w_value, model.W_SmallInteger): + return w_value.value + raise UnwrappingError("expected a W_SmallInteger, got %s" % (w_value,)) + + def unwrap_char(self, w_char): + from pypy.lang.smalltalk import constants + w_class = w_char.getclass(self) + if not w_class.is_same_object(self.w_Character): + raise UnwrappingError("expected character, got %s" % (w_class, )) + w_ord = w_char.fetch(constants.CHARACTER_VALUE_INDEX) + w_class = w_ord.getclass(self) + if not w_class.is_same_object(self.w_SmallInteger): + raise UnwrappingError("expected smallint from character, got %s" % (w_class, )) + + assert isinstance(w_ord, model.W_SmallInteger) + return chr(w_ord.value) + + def unwrap_float(self, w_v): + from pypy.lang.smalltalk import model + if isinstance(w_v, model.W_Float): return w_v.value + elif isinstance(w_v, model.W_SmallInteger): return float(w_v.value) + raise UnwrappingError() + + + +def bootstrap_class(space, instsize, w_superclass=None, w_metaclass=None, + name='?', format=shadow.POINTERS, varsized=False): + from pypy.lang.smalltalk import model + w_class = model.W_PointersObject(w_metaclass, 0) + # a dummy placeholder for testing + # XXX + s = instantiate(shadow.ClassShadow) + s.space = space + s._w_self = w_class + s.w_superclass = w_superclass + s.name = name + s.instance_size = instsize + s.instance_kind = format + s.w_methoddict = None + s.instance_varsized = varsized or format != shadow.POINTERS + s.invalid = False + w_class.store_shadow(s) + return w_class Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/squeakimage.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/squeakimage.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/squeakimage.py Sun May 25 16:09:07 2008 @@ -1,7 +1,7 @@ import py import os +from pypy.lang.smalltalk import constants from pypy.lang.smalltalk import model -from pypy.lang.smalltalk import objtable, utility from pypy.rlib import objectmodel from pypy.lang.smalltalk.tool.bitmanipulation import splitter @@ -69,7 +69,8 @@ # ____________________________________________________________ class ImageReader(object): - def __init__(self, stream): + def __init__(self, space, stream): + self.space = space self.stream = stream self.chunks = {} self.chunklist = [] @@ -124,16 +125,13 @@ chunk.g_object.init_w_object() def assign_prebuilt_constants(self): - from pypy.lang.smalltalk import classtable, constants # assign w_objects for objects that are already in classtable for name, so_index in constants.classes_in_special_object_table.items(): - # w_object = getattr(classtable, "w_" + name) - w_object = classtable.classtable["w_" + name] + w_object = self.space.classtable["w_" + name] self.special_object(so_index).w_object = w_object # assign w_objects for objects that are already in objtable for name, so_index in constants.objects_in_special_object_table.items(): - # w_object = getattr(objtable, "w_" + name) - w_object = objtable.get_objtable()["w_" + name] + w_object = self.space.objtable["w_" + name] self.special_object(so_index).w_object = w_object def special_object(self, index): @@ -173,14 +171,14 @@ kind, size, format, classid, idhash = ( splitter[2,6,4,5,12](self.stream.next())) assert kind == 3 - return ImageChunk(size, format, classid, idhash), self.stream.count - 4 + return ImageChunk(self.space, size, format, classid, idhash), self.stream.count - 4 def read_2wordobjectheader(self): assert self.stream.peek() & 3 == 1 #kind classid = self.stream.next() - 01 # remove headertype to get pointer kind, size, format, _, idhash = splitter[2,6,4,5,12](self.stream.next()) assert kind == 1 - return ImageChunk(size, format, classid, idhash), self.stream.count - 4 + return ImageChunk(self.space, size, format, classid, idhash), self.stream.count - 4 def read_3wordobjectheader(self): kind, size = splitter[2,30](self.stream.next()) @@ -189,22 +187,21 @@ classid = self.stream.next() - 00 # remove headertype to get pointer kind, _, format, _, idhash = splitter[2,6,4,5,12](self.stream.next()) assert kind == 0 - return ImageChunk(size, format, classid, idhash), self.stream.count - 4 + return ImageChunk(self.space, size, format, classid, idhash), self.stream.count - 4 # ____________________________________________________________ class SqueakImage(object): - def from_reader(self, reader): - from pypy.lang.smalltalk import constants, classtable + def from_reader(self, space, reader): + from pypy.lang.smalltalk import constants self.special_objects = [g_object.w_object for g_object in reader.chunks[reader.specialobjectspointer] .g_object.pointers] - from pypy.lang.smalltalk import objtable for name, idx in constants.objects_in_special_object_table.items(): - objtable.get_objtable()["w_" + name] = self.special_objects[idx] + space.objtable["w_" + name] = self.special_objects[idx] def special(self, index): return self.special_objects[index] @@ -219,7 +216,8 @@ GenericObject from the image chunks, and uses them as starting point for the actual create of pypy.lang.smalltalk.model classes. """ - def __init__(self): + def __init__(self, space): + self.space = space self.owner = None def isinitialized(self): @@ -229,7 +227,7 @@ self.owner = reader self.value = value self.size = -1 - self.w_object = utility.wrap_int(value) + self.w_object = self.space.wrap_int(value) def initialize(self, chunk, reader): self.owner = reader @@ -256,7 +254,7 @@ def decode_pointer(self, pointer): if (pointer & 1) == 1: - small_int = GenericObject() + small_int = GenericObject(self.space) small_int.initialize_int(pointer >> 1, self.owner) return small_int else: @@ -369,20 +367,19 @@ header = self.chunk.data[0] w_compiledmethod.setheader(header>>1) # We untag before giving header for i in range(1,w_compiledmethod.literalsize+1): - w_compiledmethod.literalatput0(i, self.decode_pointer(self.chunk.data[i]).w_object) + w_compiledmethod.literalatput0( + self.space, i, self.decode_pointer(self.chunk.data[i]).w_object) bbytes = self.get_bytes()[(w_compiledmethod.literalsize + 1)*4:] - # XXX assert mirrorcache.get_or_build(self.g_class.w_object) is - # ct.m_CompiledMethod w_compiledmethod.bytes = ''.join(bbytes) class ImageChunk(object): - def __init__(self, size, format, classid, hash12): + def __init__(self, space, size, format, classid, hash12): self.size = size self.format = format self.classid = classid self.hash12 = hash12 self.data = None - self.g_object = GenericObject() + self.g_object = GenericObject(space) def __eq__(self, other): "(for testing)" Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_interpreter.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_interpreter.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_interpreter.py Sun May 25 16:09:07 2008 @@ -1,10 +1,10 @@ import py from pypy.lang.smalltalk import model, interpreter, primitives, shadow -from pypy.lang.smalltalk import objtable, classtable, utility -from pypy.lang.smalltalk.utility import wrap_int, wrap_char, wrap_string, \ - unwrap_int +from pypy.lang.smalltalk import space as objspace -mockclass = classtable.bootstrap_class +mockclass = objspace.bootstrap_class + +space = objspace.ObjSpace() # expose the bytecode's values as global constants. # Bytecodes that have a whole range are exposed as global functions: @@ -29,54 +29,54 @@ # Install faked compiled methods that just invoke the primitive: for (w_class, primnum, argsize, methname) in methods: - s_class = w_class.as_class_get_shadow() + s_class = w_class.as_class_get_shadow(space) prim_meth = model.W_CompiledMethod(0) prim_meth.primitive = primnum prim_meth.w_compiledin = w_class prim_meth.argsize = argsize s_class.installmethod(methname, prim_meth) - assert objtable.w_nil._shadow is None + assert space.w_nil._shadow is None try: func() finally: # Uninstall those methods: - assert objtable.w_nil._shadow is None + assert space.w_nil._shadow is None for (w_class, _, _, methname) in methods: - s_class = w_class.as_class_get_shadow() + s_class = w_class.as_class_get_shadow(space) del s_class.s_methoddict().methoddict[methname] def fakesymbol(s, _cache={}): try: return _cache[s] except KeyError: - result = _cache[s] = wrap_string(s) + result = _cache[s] = space.wrap_string(s) return result -def fakeliterals(*literals): +def fakeliterals(space, *literals): def fakeliteral(lit): if isinstance(lit, str): return fakesymbol(lit) elif isinstance(lit, int): - return wrap_int(lit) + return space.wrap_int(lit) elif isinstance(lit, list): lstlen = len(lit) - res = classtable.w_Array.as_class_get_shadow().new(lstlen) + res = space.w_Array.as_class_get_shadow(space).new(lstlen) for i in range(lstlen): - res.atput0(i, fakeliteral(lit[i])) + res.atput0(space, i, fakeliteral(lit[i])) return res return lit return [fakeliteral(lit) for lit in literals] -def new_interpreter(bytes, receiver=objtable.w_nil): +def new_interpreter(bytes, receiver=space.w_nil): assert isinstance(bytes, str) w_method = model.W_CompiledMethod(len(bytes)) w_method.islarge = 1 w_method.bytes = bytes w_method.argsize=2 w_method.tempsize=8 - w_frame = w_method.create_frame(receiver, ["foo", "bar"]) - interp = interpreter.Interpreter() + w_frame = w_method.create_frame(space, receiver, ["foo", "bar"]) + interp = interpreter.Interpreter(space) interp.store_w_active_context(w_frame) return interp @@ -86,12 +86,12 @@ w_method.islarge = 1 w_method.argsize=2 w_method.tempsize=8 - w_frame = w_method.create_frame("receiver", ["foo", "bar"]) - s_frame = w_frame.as_context_get_shadow() + w_frame = w_method.create_frame(space, "receiver", ["foo", "bar"]) + s_frame = w_frame.as_context_get_shadow(space) assert s_frame.w_receiver() == "receiver" assert s_frame.gettemp(0) == "foo" assert s_frame.gettemp(1) == "bar" - assert s_frame.gettemp(2) is objtable.w_nil + assert s_frame.gettemp(2) is space.w_nil s_frame.settemp(2, "spam") assert s_frame.gettemp(2) == "spam" assert s_frame.getNextBytecode() == ord("h") @@ -121,12 +121,13 @@ def test_pushReceiverBytecode(): interp = new_interpreter(pushReceiverBytecode) interp.step() - assert interp.s_active_context().top() == interp.w_active_context().as_methodcontext_get_shadow().w_receiver() + assert interp.s_active_context().top().is_same_object( + interp.w_active_context().as_methodcontext_get_shadow(space).w_receiver()) def test_pushReceiverVariableBytecode(bytecode = (pushReceiverVariableBytecode(0) + pushReceiverVariableBytecode(1) + pushReceiverVariableBytecode(2))): - w_demo = mockclass(3).as_class_get_shadow().new() + w_demo = mockclass(space, 3).as_class_get_shadow(space).new() w_demo.store(0, "egg") w_demo.store(1, "bar") w_demo.store(2, "baz") @@ -140,7 +141,7 @@ pushTemporaryVariableBytecode(1) + pushTemporaryVariableBytecode(2))): interp = new_interpreter(bytecode) - interp.w_active_context().as_methodcontext_get_shadow().settemp(2, "temp") + interp.w_active_context().as_methodcontext_get_shadow(space).settemp(2, "temp") interp.step() interp.step() interp.step() @@ -150,7 +151,7 @@ pushLiteralConstantBytecode(1) + pushLiteralConstantBytecode(2)): interp = new_interpreter(bytecode) - interp.w_active_context().as_methodcontext_get_shadow().w_method().literals = fakeliterals("a", "b", "c") + interp.w_active_context().as_methodcontext_get_shadow(space).w_method().literals = fakeliterals(space, "a", "b", "c") interp.step() interp.step() interp.step() @@ -159,89 +160,89 @@ fakesymbol("c")] def test_pushLiteralVariableBytecode(bytecode=pushLiteralVariableBytecode(0)): - w_association = mockclass(2).as_class_get_shadow().new() + w_association = mockclass(space, 2).as_class_get_shadow(space).new() w_association.store(0, "mykey") w_association.store(1, "myvalue") interp = new_interpreter(bytecode) - interp.w_active_context().as_methodcontext_get_shadow().w_method().literals = fakeliterals(w_association) + interp.w_active_context().as_methodcontext_get_shadow(space).w_method().literals = fakeliterals(space, w_association) interp.step() assert interp.s_active_context().stack() == ["myvalue"] def test_storeAndPopReceiverVariableBytecode(bytecode=storeAndPopReceiverVariableBytecode, popped=True): - shadow = mockclass(8).as_class_get_shadow() + shadow = mockclass(space, 8).as_class_get_shadow(space) for index in range(8): w_object = shadow.new() interp = new_interpreter(pushConstantTrueBytecode + bytecode(index)) - interp.w_active_context().as_methodcontext_get_shadow().store_w_receiver(w_object) + interp.w_active_context().as_methodcontext_get_shadow(space).store_w_receiver(w_object) interp.step() interp.step() if popped: assert interp.s_active_context().stack() == [] else: - assert interp.s_active_context().stack() == [interp.TRUE] + assert interp.s_active_context().stack() == [space.w_true] for test_index in range(8): if test_index == index: - assert w_object.fetch(test_index) == interp.TRUE + assert w_object.fetch(test_index).is_same_object(space.w_true) else: - assert w_object.fetch(test_index) is objtable.w_nil + assert w_object.fetch(test_index) is space.w_nil def test_storeAndPopTemporaryVariableBytecode(bytecode=storeAndPopTemporaryVariableBytecode): for index in range(8): interp = new_interpreter(pushConstantTrueBytecode + bytecode(index)) - #interp.w_active_context().as_methodcontext_get_shadow().temps = [None] * 8 + #interp.w_active_context().as_methodcontext_get_shadow(space).temps = [None] * 8 interp.step() interp.step() assert interp.s_active_context().stack() == [] - interp.w_active_context().as_methodcontext_get_shadow() + interp.w_active_context().as_methodcontext_get_shadow(space) for test_index in range(8): print interp.w_active_context()._vars if test_index == index: - assert interp.s_active_context().gettemp(test_index) == interp.TRUE + assert interp.s_active_context().gettemp(test_index) == space.w_true else: - assert interp.s_active_context().gettemp(test_index) != interp.TRUE + assert interp.s_active_context().gettemp(test_index) != space.w_true def test_pushConstantTrueBytecode(): interp = new_interpreter(pushConstantTrueBytecode) interp.step() - assert interp.s_active_context().pop() == interp.TRUE + assert interp.s_active_context().pop().is_same_object(space.w_true) assert interp.s_active_context().stack() == [] def test_pushConstantFalseBytecode(): interp = new_interpreter(pushConstantFalseBytecode) interp.step() - assert interp.s_active_context().pop() == interp.FALSE + assert interp.s_active_context().pop().is_same_object(space.w_false) assert interp.s_active_context().stack() == [] def test_pushConstantNilBytecode(): interp = new_interpreter(pushConstantNilBytecode) interp.step() - assert interp.s_active_context().pop() == interp.NIL + assert interp.s_active_context().pop().is_same_object(space.w_nil) assert interp.s_active_context().stack() == [] def test_pushConstantMinusOneBytecode(): interp = new_interpreter(pushConstantMinusOneBytecode) interp.step() - assert interp.s_active_context().pop() == interp.MINUS_ONE + assert interp.s_active_context().pop().is_same_object(space.w_minus_one) assert interp.s_active_context().stack() == [] def test_pushConstantZeroBytecode(): interp = new_interpreter(pushConstantZeroBytecode) interp.step() - assert interp.s_active_context().pop() == interp.ZERO + assert interp.s_active_context().pop().is_same_object(space.w_zero) assert interp.s_active_context().stack() == [] def test_pushConstantOneBytecode(): interp = new_interpreter(pushConstantOneBytecode) interp.step() - assert interp.s_active_context().pop() == interp.ONE + assert interp.s_active_context().pop().is_same_object(space.w_one) assert interp.s_active_context().stack() == [] def test_pushConstantTwoBytecode(): interp = new_interpreter(pushConstantTwoBytecode) interp.step() - assert interp.s_active_context().pop() == interp.TWO + assert interp.s_active_context().pop().is_same_object(space.w_two) assert interp.s_active_context().stack() == [] def test_pushActiveContextBytecode(): @@ -254,7 +255,7 @@ interp = new_interpreter(pushConstantZeroBytecode + duplicateTopBytecode) interp.step() interp.step() - assert interp.s_active_context().stack() == [interp.ZERO, interp.ZERO] + assert interp.s_active_context().stack() == [space.w_zero, space.w_zero] def test_bytecodePrimBitAnd(): interp = new_interpreter(pushConstantOneBytecode + pushConstantTwoBytecode + bytecodePrimBitAnd) @@ -284,7 +285,7 @@ interp = new_interpreter(pushConstantOneBytecode + bytecodePrimClass) interp.step() interp.step() - assert interp.s_active_context().pop() == classtable.w_SmallInteger + assert interp.s_active_context().pop() == space.w_SmallInteger assert interp.s_active_context().stack() == [] def test_bytecodePrimSubtract(): @@ -332,19 +333,19 @@ interp.step() interp.step() interp.step() - assert interp.s_active_context().pop() == interpreter.Interpreter.FALSE + assert interp.s_active_context().pop() == space.w_false assert interp.s_active_context().stack() == [] interp = new_interpreter(pushConstantOneBytecode + pushConstantOneBytecode + bytecodePrimEquivalent) interp.step() interp.step() interp.step() - assert interp.s_active_context().pop() == interpreter.Interpreter.TRUE + assert interp.s_active_context().pop() == space.w_true assert interp.s_active_context().stack() == [] def test_bytecodePrimNew(): - w_fakeclassclass = mockclass(10, name='fakeclassclass') - w_fakeclass = mockclass(1, name='fakeclass', varsized=False, + w_fakeclassclass = mockclass(space, 10, name='fakeclassclass') + w_fakeclass = mockclass(space, 1, name='fakeclass', varsized=False, w_metaclass=w_fakeclassclass) interp = new_interpreter(bytecodePrimNew) interp.s_active_context().push(w_fakeclass) @@ -353,27 +354,27 @@ interp.step) w_fakeinst = interp.s_active_context().pop() assert interp.s_active_context().stack() == [] - assert w_fakeinst.getclass().is_same_object(w_fakeclass) + assert w_fakeinst.getclass(space).is_same_object(w_fakeclass) assert w_fakeinst.size() == 1 def test_bytecodePrimNewWithArg(): - w_fakeclassclass = mockclass(10, name='fakeclassclass') - w_fakeclass = mockclass(1, name='fakeclass', varsized=True, + w_fakeclassclass = mockclass(space, 10, name='fakeclassclass') + w_fakeclass = mockclass(space, 1, name='fakeclass', varsized=True, w_metaclass=w_fakeclassclass) interp = new_interpreter(bytecodePrimNewWithArg) interp.s_active_context().push(w_fakeclass) - interp.s_active_context().push(interpreter.Interpreter.TWO) + interp.s_active_context().push(space.w_two) run_with_faked_methods( [[w_fakeclassclass, primitives.NEW_WITH_ARG, 1, "new:"]], interp.step) w_fakeinst = interp.s_active_context().pop() assert interp.s_active_context().stack() == [] - assert w_fakeinst.getclass().is_same_object(w_fakeclass) + assert w_fakeinst.getclass(space).is_same_object(w_fakeclass) assert w_fakeinst.size() == 3 def test_bytecodePrimSize(): - w_fakeclass = mockclass(2, name='fakeclass', varsized=True) - w_fakeinst = w_fakeclass.as_class_get_shadow().new(5) + w_fakeclass = mockclass(space, 2, name='fakeclass', varsized=True) + w_fakeinst = w_fakeclass.as_class_get_shadow(space).new(5) interp = new_interpreter(bytecodePrimSize) interp.s_active_context().push(w_fakeinst) run_with_faked_methods( @@ -388,78 +389,78 @@ # bytecodes - the bytecode to be executed def sendBytecodesTest(w_class, w_object, bytecodes): for bytecode, result in [ (returnReceiver, w_object), - (returnTrue, interpreter.Interpreter.TRUE), - (returnFalse, interpreter.Interpreter.FALSE), - (returnNil, interpreter.Interpreter.NIL), - (returnTopFromMethod, interpreter.Interpreter.ONE) ]: - shadow = w_class.as_class_get_shadow() + (returnTrue, space.w_true), + (returnFalse, space.w_false), + (returnNil, space.w_nil), + (returnTopFromMethod, space.w_one) ]: + shadow = w_class.as_class_get_shadow(space) w_method = model.W_CompiledMethod(2) w_method.bytes = pushConstantOneBytecode + bytecode shadow.installmethod("foo", w_method) interp = new_interpreter(bytecodes) - interp.w_active_context().as_methodcontext_get_shadow().w_method().literals = fakeliterals("foo") + interp.w_active_context().as_methodcontext_get_shadow(space).w_method().literals = fakeliterals(space, "foo") interp.s_active_context().push(w_object) callerContext = interp.w_active_context() interp.step() assert interp.s_active_context().w_sender() == callerContext assert interp.s_active_context().stack() == [] - assert interp.w_active_context().as_methodcontext_get_shadow().w_receiver() == w_object - assert interp.w_active_context().as_methodcontext_get_shadow().w_method() == shadow.s_methoddict().methoddict["foo"] - assert callerContext.as_context_get_shadow().stack() == [] + assert interp.w_active_context().as_methodcontext_get_shadow(space).w_receiver().is_same_object(w_object) + assert interp.w_active_context().as_methodcontext_get_shadow(space).w_method().is_same_object(shadow.s_methoddict().methoddict["foo"]) + assert callerContext.as_context_get_shadow(space).stack() == [] interp.step() interp.step() assert interp.w_active_context() == callerContext assert interp.s_active_context().stack() == [result] def test_sendLiteralSelectorBytecode(): - w_class = mockclass(0) - w_object = w_class.as_class_get_shadow().new() + w_class = mockclass(space, 0) + w_object = w_class.as_class_get_shadow(space).new() sendBytecodesTest(w_class, w_object, sendLiteralSelectorBytecode(0)) def test_fibWithArgument(): bytecode = ''.join(map(chr, [ 16, 119, 178, 154, 118, 164, 11, 112, 16, 118, 177, 224, 112, 16, 119, 177, 224, 176, 124 ])) - shadow = mockclass(0).as_class_get_shadow() + shadow = mockclass(space, 0).as_class_get_shadow(space) method = model.W_CompiledMethod(len(bytecode)) method.literalsize = 1 method.bytes = bytecode method.argsize = 1 method.tempsize = 1 - method.literals = fakeliterals("fib:") + method.literals = fakeliterals(space, "fib:") shadow.installmethod("fib:", method) w_object = shadow.new() interp = new_interpreter(sendLiteralSelectorBytecode(16) + returnTopFromMethod) - interp.w_active_context().as_methodcontext_get_shadow().w_method().literals = fakeliterals("fib:") + interp.w_active_context().as_methodcontext_get_shadow(space).w_method().literals = fakeliterals(space, "fib:") interp.s_active_context().push(w_object) - interp.s_active_context().push(wrap_int(8)) + interp.s_active_context().push(space.wrap_int(8)) result = interp.interpret() - assert unwrap_int(result) == 34 + assert space.unwrap_int(result) == 34 def test_send_to_primitive(): def test(): interp = new_interpreter(sendLiteralSelectorBytecode(1 + 16)) - interp.w_active_context().as_methodcontext_get_shadow().w_method().literals = fakeliterals("foo", "sub") - interp.s_active_context().push(wrap_int(50)) - interp.s_active_context().push(wrap_int(8)) + interp.w_active_context().as_methodcontext_get_shadow(space).w_method().literals = fakeliterals(space, "foo", "sub") + interp.s_active_context().push(space.wrap_int(50)) + interp.s_active_context().push(space.wrap_int(8)) callerContext = interp.w_active_context() interp.step() assert interp.w_active_context() is callerContext assert len(interp.s_active_context().stack()) == 1 w_result = interp.s_active_context().pop() - assert unwrap_int(w_result) == 42 + assert space.unwrap_int(w_result) == 42 run_with_faked_methods( - [[classtable.w_SmallInteger, primitives.SUBTRACT, + [[space.w_SmallInteger, primitives.SUBTRACT, 1, "sub"]], test) def test_longJumpIfTrue(): interp = new_interpreter(longJumpIfTrue(0) + chr(15) + longJumpIfTrue(0) + chr(15)) - interp.s_active_context().push(interp.FALSE) + interp.s_active_context().push(space.w_false) pc = interp.s_active_context().pc() + 2 interp.step() assert interp.s_active_context().pc() == pc - interp.s_active_context().push(interp.TRUE) + interp.s_active_context().push(space.w_true) pc = interp.s_active_context().pc() + 2 interp.step() assert interp.s_active_context().pc() == pc + 15 @@ -504,7 +505,7 @@ interp = new_interpreter(pushConstantTrueBytecode + popStackBytecode) interp.step() - assert interp.s_active_context().stack() == [interp.TRUE] + assert interp.s_active_context().stack() == [space.w_true] interp.step() assert interp.s_active_context().stack() == [] @@ -524,14 +525,14 @@ test_pushLiteralVariableBytecode(extendedPushBytecode + chr((3<<6) + 0)) def storeAssociation(bytecode): - w_association = mockclass(2).as_class_get_shadow().new() + w_association = mockclass(space, 2).as_class_get_shadow(space).new() w_association.store(0, "mykey") w_association.store(1, "myvalue") interp = new_interpreter(pushConstantOneBytecode + bytecode) - interp.w_active_context().as_methodcontext_get_shadow().w_method().literals = fakeliterals(w_association) + interp.w_active_context().as_methodcontext_get_shadow(space).w_method().literals = fakeliterals(space, w_association) interp.step() interp.step() - assert w_association.fetch(1) == interp.ONE + assert w_association.fetch(1).is_same_object(space.w_one) def test_extendedStoreAndPopBytecode(): test_storeAndPopReceiverVariableBytecode(lambda index: extendedStoreAndPopBytecode + chr((0<<6) + index)) @@ -546,7 +547,7 @@ def test_callPrimitiveAndPush_fallback(): interp = new_interpreter(bytecodePrimAdd) - shadow = mockclass(0).as_class_get_shadow() + shadow = mockclass(space, 0).as_class_get_shadow(space) w_method = model.W_CompiledMethod(0) w_method.argsize = 1 w_method.tempsize = 1 @@ -555,11 +556,11 @@ w_object = shadow.new() interp.s_active_context().push(w_object) - interp.s_active_context().push(interp.ONE) + interp.s_active_context().push(space.w_one) interp.step() - assert interp.w_active_context().as_methodcontext_get_shadow().w_method() == shadow.s_methoddict().methoddict["+"] + assert interp.w_active_context().as_methodcontext_get_shadow(space).w_method() == shadow.s_methoddict().methoddict["+"] assert interp.s_active_context().w_receiver() is w_object - assert interp.w_active_context().as_methodcontext_get_shadow().gettemp(0) == interp.ONE + assert interp.w_active_context().as_methodcontext_get_shadow(space).gettemp(0).is_same_object(space.w_one) assert interp.s_active_context().stack() == [] def test_bytecodePrimBool(): @@ -570,39 +571,39 @@ bytecodePrimEqual + bytecodePrimNotEqual) for i in range(6): - interp.s_active_context().push(interp.ONE) - interp.s_active_context().push(interp.TWO) + interp.s_active_context().push(space.w_one) + interp.s_active_context().push(space.w_two) interp.step() - assert interp.s_active_context().stack() == [interp.TRUE, interp.FALSE, - interp.TRUE, interp.FALSE, - interp.FALSE, interp.TRUE] + assert interp.s_active_context().stack() == [space.w_true, space.w_false, + space.w_true, space.w_false, + space.w_false, space.w_true] def test_singleExtendedSendBytecode(): - w_class = mockclass(0) - w_object = w_class.as_class_get_shadow().new() + w_class = mockclass(space, 0) + w_object = w_class.as_class_get_shadow(space).new() sendBytecodesTest(w_class, w_object, singleExtendedSendBytecode + chr((0<<5)+0)) def test_singleExtendedSuperBytecode(bytecode=singleExtendedSuperBytecode + chr((0<<5) + 0)): - w_supersuper = mockclass(0) - w_super = mockclass(0, w_superclass=w_supersuper) - w_class = mockclass(0, w_superclass=w_super) - w_object = w_class.as_class_get_shadow().new() + w_supersuper = mockclass(space, 0) + w_super = mockclass(space, 0, w_superclass=w_supersuper) + w_class = mockclass(space, 0, w_superclass=w_super) + w_object = w_class.as_class_get_shadow(space).new() # first call method installed in w_class bytecodes = singleExtendedSendBytecode + chr(0) # which does a call to its super meth1 = model.W_CompiledMethod(2) meth1.bytes = pushReceiverBytecode + bytecode - w_class.as_class_get_shadow().installmethod("foo", meth1) + w_class.as_class_get_shadow(space).installmethod("foo", meth1) # and that one again to its super meth2 = model.W_CompiledMethod(2) meth2.bytes = pushReceiverBytecode + bytecode - w_super.as_class_get_shadow().installmethod("foo", meth2) + w_super.as_class_get_shadow(space).installmethod("foo", meth2) meth3 = model.W_CompiledMethod(0) - w_supersuper.as_class_get_shadow().installmethod("foo", meth3) - meth1.literals = fakeliterals("foo") - meth2.literals = fakeliterals("foo") + w_supersuper.as_class_get_shadow(space).installmethod("foo", meth3) + meth1.literals = fakeliterals(space, "foo") + meth2.literals = fakeliterals(space, "foo") interp = new_interpreter(bytecodes) - interp.w_active_context().as_methodcontext_get_shadow().w_method().literals = fakeliterals("foo") + interp.w_active_context().as_methodcontext_get_shadow(space).w_method().literals = fakeliterals(space, "foo") interp.s_active_context().push(w_object) interp.step() for w_specificclass in [w_super, w_supersuper]: @@ -611,19 +612,19 @@ interp.step() assert interp.s_active_context().w_sender() == callerContext assert interp.s_active_context().stack() == [] - assert interp.w_active_context().as_methodcontext_get_shadow().w_receiver() == w_object - meth = w_specificclass.as_class_get_shadow().s_methoddict().methoddict["foo"] - assert interp.w_active_context().as_methodcontext_get_shadow().w_method() == meth - assert callerContext.as_context_get_shadow().stack() == [] + assert interp.w_active_context().as_methodcontext_get_shadow(space).w_receiver() == w_object + meth = w_specificclass.as_class_get_shadow(space).s_methoddict().methoddict["foo"] + assert interp.w_active_context().as_methodcontext_get_shadow(space).w_method() == meth + assert callerContext.as_context_get_shadow(space).stack() == [] def test_secondExtendedSendBytecode(): - w_class = mockclass(0) - w_object = w_class.as_class_get_shadow().new() + w_class = mockclass(space, 0) + w_object = w_class.as_class_get_shadow(space).new() sendBytecodesTest(w_class, w_object, secondExtendedSendBytecode + chr(0)) def test_doubleExtendedDoAnythinBytecode(): - w_class = mockclass(0) - w_object = w_class.as_class_get_shadow().new() + w_class = mockclass(space, 0) + w_object = w_class.as_class_get_shadow(space).new() sendBytecodesTest(w_class, w_object, doubleExtendedDoAnythingBytecode + chr((0<<5) + 0) + chr(0)) @@ -645,10 +646,10 @@ storeAssociation(doubleExtendedDoAnythingBytecode + chr(7<<5) + chr(0)) -def interpret_bc(bcodes, literals, receiver=objtable.w_nil): +def interpret_bc(bcodes, literals, receiver=space.w_nil): bcode = "".join([chr(x) for x in bcodes]) interp = new_interpreter(bcode, receiver=receiver) - interp.w_active_context().as_methodcontext_get_shadow().w_method().literals = literals + interp.w_active_context().as_methodcontext_get_shadow(space).w_method().literals = literals return interp.interpret() # tests: bytecodePrimValue & bytecodePrimValueWithArg @@ -660,7 +661,7 @@ # ^ [ 3 + 4 ] value assert interpret_bc( [ 137, 117, 200, 164, 4, 32, 33, 176, 125, 201, 124], - fakeliterals(wrap_int(3), wrap_int(4))).value == 7 + fakeliterals(space, space.wrap_int(3), space.wrap_int(4))).value == 7 def test_bc_x_plus_x_plus_1(): @@ -672,7 +673,7 @@ assert interpret_bc( [ 137, 118, 200, 164, 7, 104, 16, 16, 176, 118, 176, 125, 32, 202, 124 ], - fakeliterals(wrap_int(3))).value == 7 + fakeliterals(space, space.wrap_int(3))).value == 7 def test_bc_x_plus_y(): # value2 @@ -685,9 +686,9 @@ assert interpret_bc( [ 137, 119, 200, 164, 6, 105, 104, 16, 17, 176, 125, 33, 34, 240, 124 ], - fakeliterals("value:value:", wrap_int(3), wrap_int(4))).value == 7 + fakeliterals(space, "value:value:", space.wrap_int(3), space.wrap_int(4))).value == 7 run_with_faked_methods( - [[classtable.w_BlockContext, primitives.PRIMITIVE_VALUE, + [[space.w_BlockContext, primitives.PRIMITIVE_VALUE, 2, "value:value:"]], test) @@ -699,7 +700,7 @@ # ^ [ self ] value assert interpret_bc( [ 137, 117, 200, 164, 2, 112, 125, 201, 124 ], - fakeliterals(wrap_int(3))) is objtable.w_nil + fakeliterals(space, space.wrap_int(3))) is space.w_nil def test_bc_value_return(): # valueReturn @@ -709,7 +710,7 @@ # [ ^ 1 ] value. ^ 2 assert interpret_bc( [ 137, 117, 200, 164, 2, 118, 124, 201, 135, 119, 124 ], - fakeliterals()).value == 1 + fakeliterals(space, )).value == 1 def test_bc_value_with_args(): # valueWithArgs @@ -722,10 +723,10 @@ [ 137, 119, 200, 164, 6, 105, 104, 16, 17, 177, 125, 33, 224, 124 ], - fakeliterals("valueWithArguments:", + fakeliterals(space, "valueWithArguments:", [3, 2])).value == 1 run_with_faked_methods( - [[classtable.w_BlockContext, primitives.PRIMITIVE_VALUE_WITH_ARGS, + [[space.w_BlockContext, primitives.PRIMITIVE_VALUE_WITH_ARGS, 1, "valueWithArguments:"]], test) @@ -734,9 +735,9 @@ def test(): assert interpret_bc( [ 32, 118, 192, 124], - fakeliterals("a")) == wrap_char("a") + fakeliterals(space, "a")) == space.wrap_char("a") run_with_faked_methods( - [[classtable.w_String, primitives.STRING_AT, 1, "at:"]], + [[space.w_String, primitives.STRING_AT, 1, "at:"]], test) def test_bc_primBytecodeAtPut_string(): @@ -744,21 +745,21 @@ def test(): assert interpret_bc( [ 32, 118, 33, 193, 124 ], - fakeliterals("a", wrap_char("b"))) == wrap_char("b") + fakeliterals(space, "a", space.wrap_char("b"))) == space.wrap_char("b") run_with_faked_methods( - [[classtable.w_String, primitives.STRING_AT_PUT, 2, "at:put:"]], + [[space.w_String, primitives.STRING_AT_PUT, 2, "at:put:"]], test) def test_bc_primBytecodeAt_with_instvars(): # ^ self at: 1 - w_fakeclass = mockclass(1, name='fakeclass', varsized=True) - w_fakeinst = w_fakeclass.as_class_get_shadow().new(1) - w_fakeinst.store(0, wrap_char("a")) # static slot 0: instance variable - w_fakeinst.store(1, wrap_char("b")) # varying slot 1 + w_fakeclass = mockclass(space, 1, name='fakeclass', varsized=True) + w_fakeinst = w_fakeclass.as_class_get_shadow(space).new(1) + w_fakeinst.store(0, space.wrap_char("a")) # static slot 0: instance variable + w_fakeinst.store(1, space.wrap_char("b")) # varying slot 1 def test(): - assert utility.unwrap_char(interpret_bc( + assert space.unwrap_char(interpret_bc( [112, 118, 192, 124], - fakeliterals(), + fakeliterals(space, ), receiver=w_fakeinst)) == "b" run_with_faked_methods( [[w_fakeclass, primitives.AT, 1, "at:"]], @@ -766,17 +767,17 @@ def test_bc_primBytecodeAtPut_with_instvars(): # ^ self at: 1 put: #b - w_fakeclass = mockclass(1, name='fakeclass', varsized=True) - w_fakeinst = w_fakeclass.as_class_get_shadow().new(1) - w_fakeinst.store(0, wrap_char("a")) # static slot 0: instance variable - w_fakeinst.store(1, wrap_char("a")) # varying slot 1 + w_fakeclass = mockclass(space, 1, name='fakeclass', varsized=True) + w_fakeinst = w_fakeclass.as_class_get_shadow(space).new(1) + w_fakeinst.store(0, space.wrap_char("a")) # static slot 0: instance variable + w_fakeinst.store(1, space.wrap_char("a")) # varying slot 1 def test(): - assert utility.unwrap_char(interpret_bc( + assert space.unwrap_char(interpret_bc( [0x70, 0x76, 0x20, 0xc1, 0x7c], - fakeliterals(wrap_char("b")), + fakeliterals(space, space.wrap_char("b")), receiver=w_fakeinst)) == "b" - assert utility.unwrap_char(w_fakeinst.fetch(0)) == "a" - assert utility.unwrap_char(w_fakeinst.fetch(1)) == "b" + assert space.unwrap_char(w_fakeinst.fetch(0)) == "a" + assert space.unwrap_char(w_fakeinst.fetch(1)) == "b" run_with_faked_methods( [[w_fakeclass, primitives.AT_PUT, 2, "at:put:"]], test) @@ -787,9 +788,9 @@ # ^ self objectAt: 2 put: 3. changes the first literal to 3 # ^ self objectAt: 2. yields the new first literal (3) prim_meth = model.W_CompiledMethod(header=1024) - prim_meth.literals = fakeliterals(22) - oal = fakeliterals("objectAt:") - oalp = fakeliterals("objectAt:put:", 3) + prim_meth.literals = fakeliterals(space, 22) + oal = fakeliterals(space, "objectAt:") + oalp = fakeliterals(space, "objectAt:put:", 3) def test(): assert interpret_bc( [112, 118, 224, 124], oal, receiver=prim_meth).value == 1024 @@ -800,8 +801,8 @@ assert interpret_bc( [112, 119, 224, 124], oal, receiver=prim_meth).value == 3 run_with_faked_methods( - [[classtable.w_CompiledMethod, primitives.OBJECT_AT, 1, "objectAt:"], - [classtable.w_CompiledMethod, primitives.OBJECT_AT_PUT, 2, "objectAt:put:"]], + [[space.w_CompiledMethod, primitives.OBJECT_AT, 1, "objectAt:"], + [space.w_CompiledMethod, primitives.OBJECT_AT_PUT, 2, "objectAt:put:"]], test) def test_runwithtrace(): Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_miniimage.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_miniimage.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_miniimage.py Sun May 25 16:09:07 2008 @@ -6,25 +6,21 @@ from pypy.lang.smalltalk import model from pypy.lang.smalltalk import constants from pypy.lang.smalltalk import interpreter -from pypy.lang.smalltalk import objtable -from pypy.lang.smalltalk import classtable from pypy.lang.smalltalk import shadow -from pypy.lang.smalltalk import utility +from pypy.lang.smalltalk import space as objspace # lazy initialization of test data, ie ImageReader and Float class def setup_module(module, filename='mini.image'): - # XXX XXX find a way to get rid of global state - global mini_image - global reader - global image - mini_image = py.magic.autopath().dirpath().dirpath().join(filename) - reader = open_miniimage() + space = objspace.ObjSpace() + module.mini_image = py.magic.autopath().dirpath().dirpath().join(filename) + module.reader = open_miniimage(space) reader.initialize() - image = squeakimage.SqueakImage() - image.from_reader(get_reader()) + module.image = squeakimage.SqueakImage() + module.image.from_reader(space, get_reader()) + module.space = space -def open_miniimage(): - return squeakimage.ImageReader(squeakimage.Stream(mini_image.open())) +def open_miniimage(space): + return squeakimage.ImageReader(space, squeakimage.Stream(mini_image.open())) def get_reader(): return reader @@ -42,27 +38,19 @@ assert mini_image.check(dir=False) def test_read_header(): - reader = open_miniimage() + reader = open_miniimage(space) reader.read_header() assert reader.endofmemory == 0x93174 assert reader.oldbaseaddress == 0x6649000 assert reader.specialobjectspointer == 0x6668380 def test_read_all_header(): - reader = open_miniimage() + reader = open_miniimage(space) reader.read_header() next = reader.stream.peek() assert next != 0 #expects object header, which must not be 0x00000000 - -def test_number_of_objects(): - py.test.skip("we don't store globally available objects other than the special objects array") - image = get_image() - objects = objtable.objects - assert len(objects) > 0 - assert 15000 < len(objects) < 16000 - def test_all_pointers_are_valid(): reader = get_reader() for each in reader.chunks.itervalues(): @@ -76,12 +64,6 @@ reader = get_reader() assert len(reader.compactclasses) == 31 -def test_invariant(): - py.test.skip("we don't store globally available objects other than the special objects array") - image = get_image() - for each in objtable.objects: - each.invariant() - def test_float_class_size(): w_float_class = get_float_class() assert w_float_class.size() == 9 @@ -94,18 +76,23 @@ def test_str_w_object(): w_float_class = get_float_class() - w_float_class.as_class_get_shadow() + w_float_class.as_class_get_shadow(space) assert str(w_float_class) == "Float class" - assert str(w_float_class.getclass()) == "a Metaclass" #yes, with article - assert str(w_float_class.getclass().getclass()) == "Metaclass class" + w_float_class.shadow_of_my_class(space) + #assert str(w_float_class.getclass(space)) == "a Metaclass" #yes, with article + w_float_class.getclass(space).shadow_of_my_class(space) + #assert str(w_float_class.getclass(space).getclass(space)) == "Metaclass class" def test_nil_true_false(): image = get_image() w = image.special(constants.SO_NIL) + w.shadow_of_my_class(space) assert str(w) == "a UndefinedObject" #yes, with article w = image.special(constants.SO_FALSE) + w.shadow_of_my_class(space) assert str(w) == "a False" #yes, with article w = image.special(constants.SO_TRUE) + w.shadow_of_my_class(space) assert str(w) == "a True" #yes, with article def test_scheduler(): @@ -114,6 +101,7 @@ w0 = w.fetch(0) assert str(w0) == "Processor" w0 = w.fetch(1) + w0.shadow_of_my_class(space) assert str(w0) == "a ProcessorScheduler" def test_special_classes0(): @@ -150,20 +138,20 @@ def test_name_of_shadow_of_specials(): image = get_image() w_doesnot = image.special(constants.SO_DOES_NOT_UNDERSTAND) - assert repr(w_doesnot.shadow_of_my_class()) == "" - assert repr(objtable.w_nil.shadow_of_my_class()) == "" - assert repr(objtable.w_minus_one.shadow_of_my_class()) == "" - assert repr(objtable.w_zero.shadow_of_my_class()) == "" - assert repr(objtable.w_one.shadow_of_my_class()) == "" - assert repr(objtable.w_two.shadow_of_my_class()) == "" - assert repr(objtable.w_true.shadow_of_my_class()) == "" - assert repr(objtable.w_false.shadow_of_my_class()) == "" + assert repr(w_doesnot.shadow_of_my_class(space)) == "" + assert repr(space.w_nil.shadow_of_my_class(space)) == "" + assert repr(space.w_minus_one.shadow_of_my_class(space)) == "" + assert repr(space.w_zero.shadow_of_my_class(space)) == "" + assert repr(space.w_one.shadow_of_my_class(space)) == "" + assert repr(space.w_two.shadow_of_my_class(space)) == "" + assert repr(space.w_true.shadow_of_my_class(space)) == "" + assert repr(space.w_false.shadow_of_my_class(space)) == "" def test_special_classes0(): image = get_image() w = image.special(constants.SO_DOES_NOT_UNDERSTAND) assert str(w) == "doesNotUnderstand:" - assert str(w.getclass()) == "Symbol class" # for some strange reason not a symbol + assert str(w.getclass(space)) == "Symbol class" # for some strange reason not a symbol """SO_DOES_NOT_UNDERSTAND = 20 @@ -194,17 +182,17 @@ def test_lookup_abs_in_integer(int=10): image = get_image() - interp = interpreter.Interpreter() + interp = interpreter.Interpreter(space) w_object = model.W_SmallInteger(int) # Should get this from w_object w_smallint_class = image.special(constants.SO_SMALLINTEGER_CLASS) - s_class = w_object.shadow_of_my_class() + s_class = w_object.shadow_of_my_class(space) w_method = s_class.lookup("abs") assert w_method - w_frame = w_method.create_frame(w_object, []) + w_frame = w_method.create_frame(space, w_object, []) interp.store_w_active_context(w_frame) while True: @@ -219,58 +207,58 @@ def test_map_mirrors_to_classtable(): w_compiledmethod_class = image.special(constants.SO_COMPILEDMETHOD_CLASS) - assert w_compiledmethod_class is classtable.w_CompiledMethod + assert w_compiledmethod_class.is_same_object(space.w_CompiledMethod) w_nil = image.special(constants.SO_NIL) - assert w_nil is objtable.w_nil + assert w_nil.is_same_object(space.w_nil) w_true = image.special(constants.SO_TRUE) - assert w_true is objtable.w_true + assert w_true.is_same_object(space.w_true) w_false = image.special(constants.SO_FALSE) - assert w_false is objtable.w_false + assert w_false.is_same_object(space.w_false) def test_runimage(): py.test.skip("This method actually runs an image. Fails since no graphical primitives yet") from pypy.lang.smalltalk import wrapper ap = wrapper.ProcessWraper(wrapper.scheduler().active_process()) s_ctx = ap.suspended_context().as_methodcontext_get_shadow() - ap.store_suspended_context(objtable.w_nil) + ap.store_suspended_context(space.w_nil) interp = interpreter.Interpreter() interp.store_w_active_context(s_ctx.w_self()) interp.interpret() def test_compile_method(): - #py.test.skip("fails again because of the removed become. should work with new pypy become") sourcecode = """fib ^self < 2 ifTrue: [ 1 ] ifFalse: [ (self - 1) fib + (self - 2) fib ]""" - perform(w(10).getclass(), "compile:classified:notifying:", w(sourcecode), w('pypy'), w(None)) + perform(w(10).getclass(space), "compile:classified:notifying:", w(sourcecode), w('pypy'), w(None)) assert perform(w(10), "fib").is_same_object(w(89)) def w(any): + # XXX could put this on the space? if any is None: - return objtable.w_nil + return space.w_nil if isinstance(any, str): # assume never have strings of length 1 if len(any) == 1: - return utility.wrap_chr(any) + return space.wrap_chr(any) else: - return utility.wrap_string(any) + return space.wrap_string(any) if isinstance(any, int): - return utility.wrap_int(any) + return space.wrap_int(any) if isinstance(any, bool): - return utility.wrap_bool(any) + return space.wrap_bool(any) if isinstance(any, float): - return utility.wrap_float(any) + return space.wrap_float(any) else: raise Exception def perform(w_receiver, selector, *arguments_w): - interp = interpreter.Interpreter() - s_class = w_receiver.shadow_of_my_class() + interp = interpreter.Interpreter(space) + s_class = w_receiver.shadow_of_my_class(space) w_method = s_class.lookup(selector) assert w_method - w_frame = w_method.create_frame(w_receiver, list(arguments_w)) + w_frame = w_method.create_frame(space, w_receiver, list(arguments_w)) interp.store_w_active_context(w_frame) while True: try: @@ -281,22 +269,23 @@ def test_step_forged_image(): from pypy.lang.smalltalk import wrapper - ap = wrapper.ProcessWrapper(wrapper.scheduler().active_process()) - s_ctx = ap.suspended_context().as_context_get_shadow() + ap = wrapper.ProcessWrapper(space, wrapper.scheduler(space).active_process()) + s_ctx = ap.suspended_context().as_context_get_shadow(space) assert isinstance(s_ctx, shadow.MethodContextShadow) - assert s_ctx.top().is_same_object(objtable.w_true) + assert s_ctx.top().is_same_object(space.w_true) def test_step_run_something(): - setup_module(None, filename='running-something-mini.image') + from pypy.lang.smalltalk.test import test_miniimage + setup_module(test_miniimage, filename='running-something-mini.image') from pypy.lang.smalltalk import wrapper - ap = wrapper.ProcessWrapper(wrapper.scheduler().active_process()) - s_ctx = ap.suspended_context().as_context_get_shadow() - ap.store_suspended_context(objtable.w_nil) + ap = wrapper.ProcessWrapper(space, wrapper.scheduler(space).active_process()) + s_ctx = ap.suspended_context().as_context_get_shadow(space) + ap.store_suspended_context(space.w_nil) - interp = interpreter.Interpreter() + interp = interpreter.Interpreter(space) interp.store_w_active_context(s_ctx.w_self()) assert isinstance(s_ctx, shadow.MethodContextShadow) - assert interp.s_active_context().top().is_same_object(objtable.w_true) + assert interp.s_active_context().top().is_same_object(space.w_true) interp.step() interp.step() assert interp.s_active_context().top().value == 1 Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_model.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_model.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_model.py Sun May 25 16:09:07 2008 @@ -1,7 +1,11 @@ import py -from pypy.lang.smalltalk import model, shadow, objtable +from pypy.lang.smalltalk import model, shadow from pypy.lang.smalltalk.shadow import MethodNotFound -from pypy.lang.smalltalk import classtable, utility +from pypy.lang.smalltalk import space as objspace + +mockclass = objspace.bootstrap_class + +space = objspace.ObjSpace() def joinbits(values, lengths): result = 0 @@ -10,31 +14,30 @@ result += each return result -mockclass = classtable.bootstrap_class def test_new(): - w_mycls = mockclass(0) - w_myinstance = w_mycls.as_class_get_shadow().new() + w_mycls = mockclass(space, 0) + w_myinstance = w_mycls.as_class_get_shadow(space).new() assert isinstance(w_myinstance, model.W_PointersObject) - assert w_myinstance.getclass().is_same_object(w_mycls) - assert w_myinstance.shadow_of_my_class() is w_mycls.as_class_get_shadow() + assert w_myinstance.getclass(space).is_same_object(w_mycls) + assert w_myinstance.shadow_of_my_class(space) is w_mycls.as_class_get_shadow(space) def test_new_namedvars(): - w_mycls = mockclass(3) - w_myinstance = w_mycls.as_class_get_shadow().new() + w_mycls = mockclass(space, 3) + w_myinstance = w_mycls.as_class_get_shadow(space).new() assert isinstance(w_myinstance, model.W_PointersObject) - assert w_myinstance.getclass().is_same_object(w_mycls) - assert w_myinstance.fetch(0) is objtable.w_nil + assert w_myinstance.getclass(space).is_same_object(w_mycls) + assert w_myinstance.fetch(0) is space.w_nil py.test.raises(IndexError, lambda: w_myinstance.fetch(3)) w_myinstance.store(1, w_myinstance) assert w_myinstance.fetch(1) is w_myinstance def test_bytes_object(): - w_class = mockclass(0, format=shadow.BYTES) - w_bytes = w_class.as_class_get_shadow().new(20) - assert w_bytes.getclass().is_same_object(w_class) + w_class = mockclass(space, 0, format=shadow.BYTES) + w_bytes = w_class.as_class_get_shadow(space).new(20) + assert w_bytes.getclass(space).is_same_object(w_class) assert w_bytes.size() == 20 - assert w_class.as_class_get_shadow().instsize() == 0 + assert w_class.as_class_get_shadow(space).instsize() == 0 assert w_bytes.getchar(3) == "\x00" w_bytes.setchar(3, "\xAA") assert w_bytes.getchar(3) == "\xAA" @@ -42,11 +45,11 @@ py.test.raises(IndexError, lambda: w_bytes.getchar(20)) def test_word_object(): - w_class = mockclass(0, format=shadow.WORDS) - w_bytes = w_class.as_class_get_shadow().new(20) - assert w_bytes.getclass().is_same_object(w_class) + w_class = mockclass(space, 0, format=shadow.WORDS) + w_bytes = w_class.as_class_get_shadow(space).new(20) + assert w_bytes.getclass(space).is_same_object(w_class) assert w_bytes.size() == 20 - assert w_class.as_class_get_shadow().instsize() == 0 + assert w_class.as_class_get_shadow(space).instsize() == 0 assert w_bytes.getword(3) == 0 w_bytes.setword(3, 42) assert w_bytes.getword(3) == 42 @@ -54,12 +57,12 @@ py.test.raises(IndexError, lambda: w_bytes.getword(20)) def test_method_lookup(): - w_class = mockclass(0) - shadow = w_class.as_class_get_shadow() + w_class = mockclass(space, 0) + shadow = w_class.as_class_get_shadow(space) shadow.installmethod("foo", 1) shadow.installmethod("bar", 2) - w_subclass = mockclass(0, w_superclass=w_class) - subshadow = w_subclass.as_class_get_shadow() + w_subclass = mockclass(space, 0, w_superclass=w_class) + subshadow = w_subclass.as_class_get_shadow(space) assert subshadow.s_superclass() is shadow subshadow.installmethod("foo", 3) shadow.initialize_methoddict() @@ -72,11 +75,11 @@ py.test.raises(MethodNotFound, subshadow.lookup, "zork") def test_w_compiledin(): - w_super = mockclass(0) - w_class = mockclass(0, w_superclass=w_super) - supershadow = w_super.as_class_get_shadow() + w_super = mockclass(space, 0) + w_class = mockclass(space, 0, w_superclass=w_super) + supershadow = w_super.as_class_get_shadow(space) supershadow.installmethod("foo", model.W_CompiledMethod(0)) - classshadow = w_class.as_class_get_shadow() + classshadow = w_class.as_class_get_shadow(space) classshadow.initialize_methoddict() assert classshadow.lookup("foo").w_compiledin is w_super @@ -88,8 +91,8 @@ def test_hashes(): w_five = model.W_SmallInteger(5) assert w_five.gethash() == 5 - w_class = mockclass(0) - w_inst = w_class.as_class_get_shadow().new() + w_class = mockclass(space, 0) + w_inst = w_class.as_class_get_shadow(space).new() assert w_inst.hash == w_inst.UNASSIGNED_HASH h1 = w_inst.gethash() h2 = w_inst.gethash() @@ -102,30 +105,30 @@ w_method.header = 100 w_method.literals = [ 'lit1', 'lit2' ] w_method.literalsize = 2 - assert utility.unwrap_int(w_method.at0(0)) == 100 - assert w_method.at0(4) == 'lit1' - assert w_method.at0(8) == 'lit2' - assert utility.unwrap_int(w_method.at0(12)) == ord('a') - assert utility.unwrap_int(w_method.at0(13)) == ord('b') - assert utility.unwrap_int(w_method.at0(14)) == ord('c') + assert space.unwrap_int(w_method.at0(space, 0)) == 100 + assert w_method.at0(space, 4) == 'lit1' + assert w_method.at0(space, 8) == 'lit2' + assert space.unwrap_int(w_method.at0(space, 12)) == ord('a') + assert space.unwrap_int(w_method.at0(space, 13)) == ord('b') + assert space.unwrap_int(w_method.at0(space, 14)) == ord('c') def test_compiledmethod_atput0(): w_method = model.W_CompiledMethod(3) newheader = joinbits([0,2,0,0,0,0],[9,8,1,6,4,1]) assert w_method.getliteralsize() == 0 - w_method.atput0(0, utility.wrap_int(newheader)) + w_method.atput0(space, 0, space.wrap_int(newheader)) assert w_method.getliteralsize() == 8 # 2 from new header * BYTES_PER_WORD (= 4) - w_method.atput0(4, 'lit1') - w_method.atput0(8, 'lit2') - w_method.atput0(12, utility.wrap_int(ord('a'))) - w_method.atput0(13, utility.wrap_int(ord('b'))) - w_method.atput0(14, utility.wrap_int(ord('c'))) - assert utility.unwrap_int(w_method.at0(0)) == newheader - assert w_method.at0(4) == 'lit1' - assert w_method.at0(8) == 'lit2' - assert utility.unwrap_int(w_method.at0(12)) == ord('a') - assert utility.unwrap_int(w_method.at0(13)) == ord('b') - assert utility.unwrap_int(w_method.at0(14)) == ord('c') + w_method.atput0(space, 4, 'lit1') + w_method.atput0(space, 8, 'lit2') + w_method.atput0(space, 12, space.wrap_int(ord('a'))) + w_method.atput0(space, 13, space.wrap_int(ord('b'))) + w_method.atput0(space, 14, space.wrap_int(ord('c'))) + assert space.unwrap_int(w_method.at0(space, 0)) == newheader + assert w_method.at0(space, 4) == 'lit1' + assert w_method.at0(space, 8) == 'lit2' + assert space.unwrap_int(w_method.at0(space, 12)) == ord('a') + assert space.unwrap_int(w_method.at0(space, 13)) == ord('b') + assert space.unwrap_int(w_method.at0(space, 14)) == ord('c') def test_is_same_object(w_o1=model.W_PointersObject(None,0), w_o2=None): if w_o2 is None: @@ -155,20 +158,20 @@ test_not_is_same_object(model.W_SmallInteger(101), model.W_SmallInteger(100)) def test_charis_same_object(): - test_is_same_object(utility.wrap_char('a'), utility.wrap_char('a')) - test_is_same_object(utility.wrap_char('d'), utility.wrap_char('d')) + test_is_same_object(space.wrap_char('a'), space.wrap_char('a')) + test_is_same_object(space.wrap_char('d'), space.wrap_char('d')) def test_not_charis_same_object(): - test_not_is_same_object(utility.wrap_char('a'), utility.wrap_char('d')) - test_not_is_same_object(utility.wrap_char('d'), utility.wrap_int(3)) - test_not_is_same_object(utility.wrap_char('d'), utility.wrap_float(3.0)) + test_not_is_same_object(space.wrap_char('a'), space.wrap_char('d')) + test_not_is_same_object(space.wrap_char('d'), space.wrap_int(3)) + test_not_is_same_object(space.wrap_char('d'), space.wrap_float(3.0)) def test_become_pointers(): - w_clsa = mockclass(3) - w_a = w_clsa.as_class_get_shadow().new() + w_clsa = mockclass(space, 3) + w_a = w_clsa.as_class_get_shadow(space).new() - w_clsb = mockclass(4) - w_b = w_clsb.as_class_get_shadow().new() + w_clsb = mockclass(space, 4) + w_b = w_clsb.as_class_get_shadow(space).new() hasha = w_a.gethash() hashb = w_b.gethash() @@ -181,18 +184,18 @@ assert w_a.gethash() == hashb assert w_b.gethash() == hasha - assert w_a.getclass().is_same_object(w_clsb) - assert w_b.getclass().is_same_object(w_clsa) + assert w_a.getclass(space).is_same_object(w_clsb) + assert w_b.getclass(space).is_same_object(w_clsa) assert w_b.fetch(0) is w_b assert w_a.fetch(1) is w_a def test_become_with_shadow(): - w_clsa = mockclass(3) - s_clsa = w_clsa.as_class_get_shadow() - w_clsb = mockclass(4) - s_clsb = w_clsb.as_class_get_shadow() + w_clsa = mockclass(space, 3) + s_clsa = w_clsa.as_class_get_shadow(space) + w_clsb = mockclass(space, 4) + s_clsb = w_clsb.as_class_get_shadow(space) res = w_clsa.become(w_clsb) assert res - assert w_clsa.as_class_get_shadow() is s_clsb - assert w_clsb.as_class_get_shadow() is s_clsa + assert w_clsa.as_class_get_shadow(space) is s_clsb + assert w_clsb.as_class_get_shadow(space) is s_clsa Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_primitives.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_primitives.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_primitives.py Sun May 25 16:09:07 2008 @@ -1,13 +1,15 @@ import py import math from pypy.lang.smalltalk.primitives import prim_table, PrimitiveFailedError -from pypy.lang.smalltalk import model, shadow -from pypy.lang.smalltalk import interpreter, utility -from pypy.lang.smalltalk import classtable, objtable, constants +from pypy.lang.smalltalk import model, shadow, interpreter +from pypy.lang.smalltalk import constants from pypy.rlib.rarithmetic import INFINITY, NAN, isinf, isnan from pypy.lang.smalltalk import primitives +from pypy.lang.smalltalk import space as objspace -mockclass = classtable.bootstrap_class +mockclass = objspace.bootstrap_class + +space = objspace.ObjSpace() class MockFrame(model.W_PointersObject): def __init__(self, stack): @@ -16,21 +18,21 @@ s_self._stack = stack s_self.store_expected_argument_count(0) def as_blockcontext_get_shadow(self): - self._shadow = shadow.BlockContextShadow(self) + self._shadow = shadow.BlockContextShadow(space, self) return self._shadow def wrap(x): - if isinstance(x, int): return utility.wrap_int(x) - if isinstance(x, float): return utility.wrap_float(x) + if isinstance(x, int): return space.wrap_int(x) + if isinstance(x, float): return space.wrap_float(x) if isinstance(x, model.W_Object): return x - if isinstance(x, str) and len(x) == 1: return utility.wrap_char(x) - if isinstance(x, str): return utility.wrap_string(x) + if isinstance(x, str) and len(x) == 1: return space.wrap_char(x) + if isinstance(x, str): return space.wrap_string(x) raise NotImplementedError def mock(stack): mapped_stack = [wrap(x) for x in stack] frame = MockFrame(mapped_stack) - interp = interpreter.Interpreter() + interp = interpreter.Interpreter(space) interp.store_w_active_context(frame) return (interp, len(stack)) @@ -181,16 +183,16 @@ assert prim(primitives.FLOAT_TRUNCATED, [4.6]).value == 4 def test_at(): - w_obj = mockclass(0, varsized=True).as_class_get_shadow().new(1) + w_obj = mockclass(space, 0, varsized=True).as_class_get_shadow(space).new(1) w_obj.store(0, "foo") assert prim(primitives.AT, [w_obj, 1]) == "foo" def test_invalid_at(): - w_obj = mockclass(0).as_class_get_shadow().new() + w_obj = mockclass(space, 0).as_class_get_shadow(space).new() prim_fails(primitives.AT, [w_obj, 1]) def test_at_put(): - w_obj = mockclass(0, varsized=1).as_class_get_shadow().new(1) + w_obj = mockclass(space, 0, varsized=1).as_class_get_shadow(space).new(1) assert prim(primitives.AT_PUT, [w_obj, 1, 22]).value == 22 assert prim(primitives.AT, [w_obj, 1]).value == 22 @@ -203,13 +205,13 @@ assert prim(primitives.AT, [w_str, 3]).value == ord('c') def test_invalid_at_put(): - w_obj = mockclass(0).as_class_get_shadow().new() + w_obj = mockclass(space, 0).as_class_get_shadow(space).new() prim_fails(primitives.AT_PUT, [w_obj, 1, 22]) def test_size(): - w_obj = mockclass(0, varsized=True).as_class_get_shadow().new(0) + w_obj = mockclass(space, 0, varsized=True).as_class_get_shadow(space).new(0) assert prim(primitives.SIZE, [w_obj]).value == 0 - w_obj = mockclass(3, varsized=True).as_class_get_shadow().new(5) + w_obj = mockclass(space, 3, varsized=True).as_class_get_shadow(space).new(5) assert prim(primitives.SIZE, [w_obj]).value == 5 def test_size_of_compiled_method(): @@ -233,7 +235,7 @@ prim_fails(primitives.OBJECT_AT, ["q", constants.CHARACTER_VALUE_INDEX+2]) def test_invalid_object_at_put(): - w_obj = mockclass(1).as_class_get_shadow().new() + w_obj = mockclass(space, 1).as_class_get_shadow(space).new() prim_fails(primitives.OBJECT_AT_PUT, [w_obj, 2, 42]) def test_string_at_put(): @@ -244,20 +246,20 @@ assert prim(primitives.STRING_AT, [test_str, i]) == wrap(exp[i-1]) def test_new(): - w_Object = classtable.classtable['w_Object'] + w_Object = space.classtable['w_Object'] w_res = prim(primitives.NEW, [w_Object]) - assert w_res.getclass().is_same_object(w_Object) + assert w_res.getclass(space).is_same_object(w_Object) def test_invalid_new(): - prim_fails(primitives.NEW, [classtable.w_String]) + prim_fails(primitives.NEW, [space.w_String]) def test_new_with_arg(): - w_res = prim(primitives.NEW_WITH_ARG, [classtable.w_String, 20]) - assert w_res.getclass().is_same_object(classtable.w_String) + w_res = prim(primitives.NEW_WITH_ARG, [space.w_String, 20]) + assert w_res.getclass(space).is_same_object(space.w_String) assert w_res.size() == 20 def test_invalid_new_with_arg(): - w_Object = classtable.classtable['w_Object'] + w_Object = space.classtable['w_Object'] prim_fails(primitives.NEW_WITH_ARG, [w_Object, 20]) def test_inst_var_at(): @@ -272,10 +274,10 @@ def test_inst_var_at_put(): # n.b.: 1-based indexing! - w_q = classtable.w_Character.as_class_get_shadow().new() + w_q = space.w_Character.as_class_get_shadow(space).new() vidx = constants.CHARACTER_VALUE_INDEX+1 ordq = ord("q") - assert prim(primitives.INST_VAR_AT, [w_q, vidx]) == objtable.w_nil + assert prim(primitives.INST_VAR_AT, [w_q, vidx]) == space.w_nil assert prim(primitives.INST_VAR_AT_PUT, [w_q, vidx, ordq]).value == ordq assert prim(primitives.INST_VAR_AT, [w_q, vidx]).value == ordq @@ -285,12 +287,12 @@ ["q", constants.CHARACTER_VALUE_INDEX+2, "t"]) def test_class(): - assert prim(primitives.CLASS, ["string"]) == classtable.w_String - assert prim(primitives.CLASS, [1]) == classtable.w_SmallInteger + assert prim(primitives.CLASS, ["string"]).is_same_object(space.w_String) + assert prim(primitives.CLASS, [1]).is_same_object(space.w_SmallInteger) def test_as_oop(): py.test.skip("not yet clear what AS_OOP returns: hash or header?") - w_obj = mockclass(0).as_class_get_shadow().new() + w_obj = mockclass(space, 0).as_class_get_shadow(space).new() w_obj.w_hash = wrap(22) assert prim(primitives.AS_OOP, [w_obj]).value == 22 @@ -299,33 +301,33 @@ def test_const_primitives(): for (code, const) in [ - (primitives.PUSH_TRUE, objtable.w_true), - (primitives.PUSH_FALSE, objtable.w_false), - (primitives.PUSH_NIL, objtable.w_nil), - (primitives.PUSH_MINUS_ONE, objtable.w_minus_one), - (primitives.PUSH_ZERO, objtable.w_zero), - (primitives.PUSH_ONE, objtable.w_one), - (primitives.PUSH_TWO, objtable.w_two), + (primitives.PUSH_TRUE, space.w_true), + (primitives.PUSH_FALSE, space.w_false), + (primitives.PUSH_NIL, space.w_nil), + (primitives.PUSH_MINUS_ONE, space.w_minus_one), + (primitives.PUSH_ZERO, space.w_zero), + (primitives.PUSH_ONE, space.w_one), + (primitives.PUSH_TWO, space.w_two), ]: - assert prim(code, [objtable.w_nil]) is const - assert prim(primitives.PUSH_SELF, [objtable.w_nil]) is objtable.w_nil + assert prim(code, [space.w_nil]).is_same_object(const) + assert prim(primitives.PUSH_SELF, [space.w_nil]).is_same_object(space.w_nil) assert prim(primitives.PUSH_SELF, ["a"]) is wrap("a") def test_boolean(): - assert prim(primitives.LESSTHAN, [1,2]) == objtable.w_true - assert prim(primitives.GREATERTHAN, [3,4]) == objtable.w_false - assert prim(primitives.LESSOREQUAL, [1,2]) == objtable.w_true - assert prim(primitives.GREATEROREQUAL, [3,4]) == objtable.w_false - assert prim(primitives.EQUAL, [2,2]) == objtable.w_true - assert prim(primitives.NOTEQUAL, [2,2]) == objtable.w_false + assert prim(primitives.LESSTHAN, [1,2]).is_same_object(space.w_true) + assert prim(primitives.GREATERTHAN, [3,4]).is_same_object(space.w_false) + assert prim(primitives.LESSOREQUAL, [1,2]).is_same_object(space.w_true) + assert prim(primitives.GREATEROREQUAL, [3,4]).is_same_object(space.w_false) + assert prim(primitives.EQUAL, [2,2]).is_same_object(space.w_true) + assert prim(primitives.NOTEQUAL, [2,2]).is_same_object(space.w_false) def test_float_boolean(): - assert prim(primitives.FLOAT_LESSTHAN, [1.0,2.0]) == objtable.w_true - assert prim(primitives.FLOAT_GREATERTHAN, [3.0,4.0]) == objtable.w_false - assert prim(primitives.FLOAT_LESSOREQUAL, [1.3,2.6]) == objtable.w_true - assert prim(primitives.FLOAT_GREATEROREQUAL, [3.5,4.9]) == objtable.w_false - assert prim(primitives.FLOAT_EQUAL, [2.2,2.2]) == objtable.w_true - assert prim(primitives.FLOAT_NOTEQUAL, [2.2,2.2]) == objtable.w_false + assert prim(primitives.FLOAT_LESSTHAN, [1.0,2.0]).is_same_object(space.w_true) + assert prim(primitives.FLOAT_GREATERTHAN, [3.0,4.0]).is_same_object(space.w_false) + assert prim(primitives.FLOAT_LESSOREQUAL, [1.3,2.6]).is_same_object(space.w_true) + assert prim(primitives.FLOAT_GREATEROREQUAL, [3.5,4.9]).is_same_object(space.w_false) + assert prim(primitives.FLOAT_EQUAL, [2.2,2.2]).is_same_object(space.w_true) + assert prim(primitives.FLOAT_NOTEQUAL, [2.2,2.2]).is_same_object(space.w_false) def test_block_copy_and_value(): # see test_interpreter for tests of these opcodes @@ -404,11 +406,11 @@ def test_new_method(): bytecode = ''.join(map(chr, [ 16, 119, 178, 154, 118, 164, 11, 112, 16, 118, 177, 224, 112, 16, 119, 177, 224, 176, 124 ])) - shadow = mockclass(0).as_class_get_shadow() - w_method = prim(primitives.NEW_METHOD, [classtable.w_CompiledMethod, len(bytecode), 1025]) - assert w_method.literalat0(0).value == 1025 + shadow = mockclass(space, 0).as_class_get_shadow(space) + w_method = prim(primitives.NEW_METHOD, [space.w_CompiledMethod, len(bytecode), 1025]) + assert w_method.literalat0(space, 0).value == 1025 assert w_method.literalsize == 2 - assert w_method.literalat0(1) is objtable.w_nil + assert w_method.literalat0(space, 1).is_same_object(space.w_nil) assert w_method.bytes == "\x00" * len(bytecode) Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_shadow.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_shadow.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_shadow.py Sun May 25 16:09:07 2008 @@ -1,27 +1,29 @@ import random -from pypy.lang.smalltalk import model, shadow, classtable, constants, objtable -from pypy.lang.smalltalk import utility +from pypy.lang.smalltalk import model, shadow, constants +from pypy.lang.smalltalk import space as objspace -w_Object = classtable.classtable['w_Object'] -w_Metaclass = classtable.classtable['w_Metaclass'] -w_MethodDict = classtable.classtable['w_MethodDict'] -w_Array = classtable.classtable['w_Array'] +space = objspace.ObjSpace() + +w_Object = space.classtable['w_Object'] +w_Metaclass = space.classtable['w_Metaclass'] +w_MethodDict = space.classtable['w_MethodDict'] +w_Array = space.classtable['w_Array'] def build_methoddict(methods): size = int(len(methods) * 1.5) - w_methoddict = w_MethodDict.as_class_get_shadow().new(size) - w_array = w_Array.as_class_get_shadow().new(size) + w_methoddict = w_MethodDict.as_class_get_shadow(space).new(size) + w_array = w_Array.as_class_get_shadow(space).new(size) for i in range(size): - w_array.store(i, objtable.w_nil) - w_methoddict.store(constants.METHODDICT_NAMES_INDEX+i, objtable.w_nil) - w_tally = utility.wrap_int(len(methods)) + w_array.store(i, space.w_nil) + w_methoddict.store(constants.METHODDICT_NAMES_INDEX+i, space.w_nil) + w_tally = space.wrap_int(len(methods)) w_methoddict.store(constants.METHODDICT_TALLY_INDEX, w_tally) w_methoddict.store(constants.METHODDICT_VALUES_INDEX, w_array) positions = range(size) random.shuffle(positions) for selector, w_compiledmethod in methods.items(): pos = positions.pop() - w_selector = utility.wrap_string(selector) + w_selector = space.wrap_string(selector) w_methoddict.store(constants.METHODDICT_NAMES_INDEX+pos, w_selector) w_array.store(pos, w_compiledmethod) return w_methoddict @@ -37,19 +39,19 @@ w_class = model.W_PointersObject(w_classofclass, size) w_class.store(constants.CLASS_SUPERCLASS_INDEX, w_superclass) w_class.store(constants.CLASS_METHODDICT_INDEX, w_methoddict) - w_class.store(constants.CLASS_FORMAT_INDEX, utility.wrap_int(format)) + w_class.store(constants.CLASS_FORMAT_INDEX, space.wrap_int(format)) if name is not None: - w_class.store(constants.CLASS_NAME_INDEX, utility.wrap_string(name)) + w_class.store(constants.CLASS_NAME_INDEX, space.wrap_string(name)) return w_class def basicshape(name, format, kind, varsized, instsize): w_class = build_smalltalk_class(name, format) - classshadow = w_class.as_class_get_shadow() + classshadow = w_class.as_class_get_shadow(space) assert classshadow.instance_kind == kind assert classshadow.isvariable() == varsized assert classshadow.instsize() == instsize assert classshadow.name == name - assert classshadow.s_superclass() is w_Object.as_class_get_shadow() + assert classshadow.s_superclass() is w_Object.as_class_get_shadow(space) def test_basic_shape(): yield basicshape, "Empty", 0x02, shadow.POINTERS, False, 0 @@ -66,7 +68,7 @@ methods = {'foo': model.W_CompiledMethod(0), 'bar': model.W_CompiledMethod(0)} w_class = build_smalltalk_class("Demo", 0x90, methods=methods) - classshadow = w_class.as_class_get_shadow() + classshadow = w_class.as_class_get_shadow(space) assert classshadow.s_methoddict().methoddict == methods def method(tempsize=3,argsize=2, bytes="abcde"): @@ -77,12 +79,12 @@ w_m.literalsize = 2 return w_m -def methodcontext(w_sender=objtable.w_nil, pc=1, stackpointer=0, stacksize=5, +def methodcontext(w_sender=space.w_nil, pc=1, stackpointer=0, stacksize=5, method=method()): - w_object = model.W_PointersObject(classtable.w_MethodContext, constants.MTHDCTX_TEMP_FRAME_START+method.tempsize+stacksize) + w_object = model.W_PointersObject(space.w_MethodContext, constants.MTHDCTX_TEMP_FRAME_START+method.tempsize+stacksize) w_object.store(constants.CTXPART_SENDER_INDEX, w_sender) - w_object.store(constants.CTXPART_PC_INDEX, utility.wrap_int(pc)) - w_object.store(constants.CTXPART_STACKP_INDEX, utility.wrap_int(method.tempsize+stackpointer)) + w_object.store(constants.CTXPART_PC_INDEX, space.wrap_int(pc)) + w_object.store(constants.CTXPART_STACKP_INDEX, space.wrap_int(method.tempsize+stackpointer)) w_object.store(constants.MTHDCTX_METHOD, method) # XXX w_object.store(constants.MTHDCTX_RECEIVER_MAP, '???') @@ -91,14 +93,14 @@ w_object.store(constants.MTHDCTX_TEMP_FRAME_START, 'el') return w_object -def blockcontext(w_sender=objtable.w_nil, pc=1, stackpointer=1, stacksize=5, +def blockcontext(w_sender=space.w_nil, pc=1, stackpointer=1, stacksize=5, home=methodcontext()): - w_object = model.W_PointersObject(classtable.w_MethodContext, constants.MTHDCTX_TEMP_FRAME_START+stacksize) + w_object = model.W_PointersObject(space.w_MethodContext, constants.MTHDCTX_TEMP_FRAME_START+stacksize) w_object.store(constants.CTXPART_SENDER_INDEX, w_sender) - w_object.store(constants.CTXPART_PC_INDEX, utility.wrap_int(pc)) - w_object.store(constants.CTXPART_STACKP_INDEX, utility.wrap_int(stackpointer)) - w_object.store(constants.BLKCTX_BLOCK_ARGUMENT_COUNT_INDEX, utility.wrap_int(54)) - w_object.store(constants.BLKCTX_INITIAL_IP_INDEX, utility.wrap_int(17)) + w_object.store(constants.CTXPART_PC_INDEX, space.wrap_int(pc)) + w_object.store(constants.CTXPART_STACKP_INDEX, space.wrap_int(stackpointer)) + w_object.store(constants.BLKCTX_BLOCK_ARGUMENT_COUNT_INDEX, space.wrap_int(54)) + w_object.store(constants.BLKCTX_INITIAL_IP_INDEX, space.wrap_int(17)) w_object.store(constants.BLKCTX_HOME_INDEX, home) w_object.store(constants.BLKCTX_STACK_START, 'el') return w_object @@ -107,9 +109,9 @@ w_m = method() w_object = methodcontext(stackpointer=3, method=w_m) w_object2 = methodcontext(w_sender=w_object) - s_object = w_object.as_methodcontext_get_shadow() + s_object = w_object.as_methodcontext_get_shadow(space) assert len(s_object.stack()) == 3 - s_object2 = w_object2.as_methodcontext_get_shadow() + s_object2 = w_object2.as_methodcontext_get_shadow(space) assert w_object2.fetch(constants.CTXPART_SENDER_INDEX) == w_object assert s_object.w_self() == w_object assert s_object2.w_self() == w_object2 @@ -139,7 +141,7 @@ w_m = method() # Point over 2 literals of size 4 w_object = methodcontext(pc=13,method=w_m) - s_object = w_object.as_methodcontext_get_shadow() + s_object = w_object.as_methodcontext_get_shadow(space) assert s_object.getbytecode() == 97 assert s_object.getbytecode() == 98 assert s_object.getbytecode() == 99 @@ -151,7 +153,7 @@ w_m = method() w_object = methodcontext(pc=13, method=w_m) old_vars = w_object._vars - s_object = w_object.as_methodcontext_get_shadow() + s_object = w_object.as_methodcontext_get_shadow(space) assert w_object._vars is None s_object.detach_shadow() assert w_object._vars == old_vars @@ -160,7 +162,7 @@ def test_attach_detach_bc(): w_object = blockcontext(pc=13) old_vars = w_object._vars - s_object = w_object.as_blockcontext_get_shadow() + s_object = w_object.as_blockcontext_get_shadow(space) assert w_object._vars is None s_object.detach_shadow() assert w_object._vars == old_vars @@ -169,12 +171,12 @@ def test_replace_to_bc(): w_object = blockcontext(pc=13) old_vars = w_object._vars - s_object = w_object.as_blockcontext_get_shadow() + s_object = w_object.as_blockcontext_get_shadow(space) s_object.detach_shadow() - s_classshadow = shadow.ClassShadow(w_object) + s_classshadow = shadow.ClassShadow(space, w_object) w_object._shadow = s_classshadow s_classshadow.invalid = False - s_newobject = w_object.as_blockcontext_get_shadow() + s_newobject = w_object.as_blockcontext_get_shadow(space) assert s_classshadow.invalid assert ([s_newobject.fetch(i) for i in range(s_newobject.size())] == [s_object.fetch(i) for i in range(s_newobject.size())]) Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_squeakimage.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_squeakimage.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_squeakimage.py Sun May 25 16:09:07 2008 @@ -1,6 +1,9 @@ import py from pypy.lang.smalltalk import squeakimage from pypy.lang.smalltalk.squeakimage import chrs2int +from pypy.lang.smalltalk import space as objspace + +space = objspace.ObjSpace() # ----- helpers ---------------------------------------------- @@ -19,7 +22,7 @@ import StringIO f = StringIO.StringIO(string) stream = squeakimage.Stream(f) - return squeakimage.ImageReader(stream) + return squeakimage.ImageReader(space, stream) # ----- tests ------------------------------------------------ @@ -91,31 +94,31 @@ def test_1wordobjectheader(): s = ints2str(joinbits([3, 1, 2, 3, 4], [2,6,4,5,12])) r = imagereader_mock(s) - assert (squeakimage.ImageChunk(1, 2, 3, 4), 0) == r.read_1wordobjectheader() + assert (squeakimage.ImageChunk(space, 1, 2, 3, 4), 0) == r.read_1wordobjectheader() def test_1wordobjectheader2(): s = ints2str(joinbits([3, 1, 2, 3, 4], [2,6,4,5,12])) r = imagereader_mock(s * 3) - assert (squeakimage.ImageChunk(1, 2, 3, 4), 0) == r.read_1wordobjectheader() - assert (squeakimage.ImageChunk(1, 2, 3, 4), 4) == r.read_1wordobjectheader() - assert (squeakimage.ImageChunk(1, 2, 3, 4), 8) == r.read_1wordobjectheader() + assert (squeakimage.ImageChunk(space, 1, 2, 3, 4), 0) == r.read_1wordobjectheader() + assert (squeakimage.ImageChunk(space, 1, 2, 3, 4), 4) == r.read_1wordobjectheader() + assert (squeakimage.ImageChunk(space, 1, 2, 3, 4), 8) == r.read_1wordobjectheader() def test_2wordobjectheader(): s = ints2str(4200 + 1, joinbits([1, 1, 2, 3, 4], [2,6,4,5,12])) r = imagereader_mock(s) - assert (squeakimage.ImageChunk(1, 2, 4200, 4), 4) == r.read_2wordobjectheader() + assert (squeakimage.ImageChunk(space, 1, 2, 4200, 4), 4) == r.read_2wordobjectheader() def test_3wordobjectheader(): s = ints2str(1701 << 2, 4200 + 0, joinbits([0, 1, 2, 3, 4], [2,6,4,5,12])) r = imagereader_mock(s) - assert (squeakimage.ImageChunk(1701, 2, 4200, 4), 8) == r.read_3wordobjectheader() + assert (squeakimage.ImageChunk(space, 1701, 2, 4200, 4), 8) == r.read_3wordobjectheader() def test_read3wordheaderobject(): size = 42 s = ints2str(size << 2, 4200 + 0, joinbits([0, 1, 2, 3, 4], [2,6,4,5,12])) r = imagereader_mock(s + '\x00\x00\x19\x66' * (size - 1)) chunk, pos = r.read_object() - chunk0 = squeakimage.ImageChunk(size, 2, 4200, 4) + chunk0 = squeakimage.ImageChunk(space, size, 2, 4200, 4) chunk0.data = [6502] * (size - 1) assert pos == 8 assert chunk0 == chunk Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_wrapper.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_wrapper.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_wrapper.py Sun May 25 16:09:07 2008 @@ -1,13 +1,15 @@ import py from pypy.lang.smalltalk import wrapper from pypy.lang.smalltalk import model -from pypy.lang.smalltalk import objtable, utility from pypy.lang.smalltalk import interpreter from pypy.lang.smalltalk.error import WrapperException, FatalError +from pypy.lang.smalltalk import space as objspace + +space = objspace.ObjSpace() def test_simpleread(): w_o = model.W_PointersObject(None, 2) - w = wrapper.Wrapper(w_o) + w = wrapper.Wrapper(space, w_o) w_o._vars[0] = "hello" assert w.read(0) == "hello" w.write(1, "b") @@ -17,7 +19,7 @@ def test_accessor_generators(): w_o = model.W_PointersObject(None, 1) - w = wrapper.LinkWrapper(w_o) + w = wrapper.LinkWrapper(space, w_o) w_o._vars[0] = "hello" assert w.next_link() == "hello" w.store_next_link("boe") @@ -25,18 +27,18 @@ def link(w_next='foo'): w_object = model.W_PointersObject(None, 1) - wrapper.LinkWrapper(w_object).store_next_link(w_next) + wrapper.LinkWrapper(space, w_object).store_next_link(w_next) return w_object def test_linked_list(): w_object = model.W_PointersObject(None,2) - w_last = link(objtable.w_nil) + w_last = link(space.w_nil) w_lb1 = link(w_last) w_lb2 = link(w_lb1) w_lb3 = link(w_lb2) w_lb4 = link(w_lb3) w_first = link(w_lb4) - linkedlist = wrapper.LinkedListWrapper(w_object) + linkedlist = wrapper.LinkedListWrapper(space, w_object) linkedlist.store_first_link(w_first) linkedlist.store_last_link(w_last) assert w_first is linkedlist.first_link() @@ -55,21 +57,21 @@ linkedlist.add_last_link(w_last) assert linkedlist.first_link() is w_first assert linkedlist.last_link() is w_last - py.test.raises(WrapperException, linkedlist.remove, objtable.w_nil) + py.test.raises(WrapperException, linkedlist.remove, space.w_nil) linkedlist.remove(w_first) assert linkedlist.first_link() is w_last linkedlist.store_first_link(w_first) - wrapper.LinkWrapper(w_first).store_next_link(w_last) + wrapper.LinkWrapper(space, w_first).store_next_link(w_last) linkedlist.remove(w_last) assert linkedlist.last_link() is w_first -def new_process(w_next=objtable.w_nil, - w_my_list=objtable.w_nil, - w_suspended_context=objtable.w_nil, +def new_process(w_next=space.w_nil, + w_my_list=space.w_nil, + w_suspended_context=space.w_nil, priority=0): - w_priority = utility.wrap_int(priority) + w_priority = space.wrap_int(priority) w_process = model.W_PointersObject(None, 4) - process = wrapper.ProcessWrapper(w_process) + process = wrapper.ProcessWrapper(space, w_process) process.store_next_link(w_next) process.store_my_list(w_my_list) process.store_suspended_context(w_suspended_context) @@ -78,13 +80,13 @@ def new_processlist(processes_w=[]): w_processlist = model.W_PointersObject(None, 2) - w_first = objtable.w_nil - w_last = objtable.w_nil + w_first = space.w_nil + w_last = space.w_nil for w_process in processes_w[::-1]: w_first = newprocess(w_first, w_processlist).w_self - if w_last is objtable.w_nil: + if w_last is space.w_nil: w_last = w_first - pl = wrapper.ProcessListWrapper(w_processlist) + pl = wrapper.ProcessListWrapper(space, w_processlist) pl.store_first_link(w_first) pl.store_last_link(w_last) return pl @@ -96,31 +98,31 @@ maxpriority = 5 prioritydict = {} w_prioritylist = model.W_PointersObject(None, maxpriority) - prioritylist = wrapper.Wrapper(w_prioritylist) + prioritylist = wrapper.Wrapper(space, w_prioritylist) for i in range(maxpriority): prioritylist.write(i, new_processlist(prioritydict.get(i, [])).w_self) return prioritylist -def new_scheduler(w_process=objtable.w_nil, prioritydict=None): +def new_scheduler(w_process=space.w_nil, prioritydict=None): priority_list = new_prioritylist(prioritydict) w_scheduler = model.W_PointersObject(None, 2) - scheduler = wrapper.SchedulerWrapper(w_scheduler) + scheduler = wrapper.SchedulerWrapper(space, w_scheduler) scheduler.store_active_process(w_process) scheduler.write(0, priority_list.w_self) return scheduler def new_semaphore(excess_signals=0): w_semaphore = model.W_PointersObject(None, 3) - semaphore = wrapper.SemaphoreWrapper(w_semaphore) - semaphore.store_excess_signals(utility.wrap_int(excess_signals)) + semaphore = wrapper.SemaphoreWrapper(space, w_semaphore) + semaphore.store_excess_signals(space.wrap_int(excess_signals)) return semaphore class TestScheduler(object): def setup_method(self, meth): self.old_scheduler = wrapper.scheduler - wrapper.scheduler = lambda: scheduler + wrapper.scheduler = lambda space: scheduler scheduler = new_scheduler() def teardown_method(self, meth): @@ -129,33 +131,33 @@ def test_put_to_sleep(self): process = new_process(priority=2) process.put_to_sleep() - process_list = wrapper.scheduler().get_process_list(2) + process_list = wrapper.scheduler(space).get_process_list(2) assert process_list.first_link() is process_list.last_link() assert process_list.first_link() is process.w_self def test_suspend_asleep(self): - interp, process, old_process = self.make_processes(4, 2, objtable.w_false, objtable.w_true) + interp, process, old_process = self.make_processes(4, 2, space.w_false, space.w_true) process.suspend(interp) - process_list = wrapper.scheduler().get_process_list(process.priority()) + process_list = wrapper.scheduler(space).get_process_list(process.priority()) assert process_list.first_link() is process_list.last_link() - assert process_list.first_link() is objtable.w_nil - assert process.my_list() is objtable.w_nil + assert process_list.first_link() is space.w_nil + assert process.my_list() is space.w_nil def test_suspend_active(self): - interp, process, old_process = self.make_processes(4, 2, objtable.w_false, objtable.w_true) + interp, process, old_process = self.make_processes(4, 2, space.w_false, space.w_true) old_process.suspend(interp) - process_list = wrapper.scheduler().get_process_list(old_process.priority()) + process_list = wrapper.scheduler(space).get_process_list(old_process.priority()) assert process_list.first_link() is process_list.last_link() - assert process_list.first_link() is objtable.w_nil - assert old_process.my_list() is objtable.w_nil - assert wrapper.scheduler().active_process() is process.w_self + assert process_list.first_link() is space.w_nil + assert old_process.my_list() is space.w_nil + assert wrapper.scheduler(space).active_process() is process.w_self def new_process_consistency(self, process, old_process, interp, old_active_context, new_active_context): - scheduler = wrapper.scheduler() + scheduler = wrapper.scheduler(space) assert interp.w_active_context() is new_active_context assert scheduler.active_process() is process.w_self - priority_list = wrapper.scheduler().get_process_list(process.priority()) + priority_list = wrapper.scheduler(space).get_process_list(process.priority()) assert priority_list.first_link() is priority_list.last_link() # activate does not remove the process from the process_list. # The caller of activate is responsible @@ -163,13 +165,13 @@ def old_process_consistency(self, old_process, old_process_context): assert old_process.suspended_context() is old_process_context - priority_list = wrapper.scheduler().get_process_list(old_process.priority()) + priority_list = wrapper.scheduler(space).get_process_list(old_process.priority()) assert priority_list.first_link() is old_process.w_self def make_processes(self, sleepingpriority, runningpriority, sleepingcontext, runningcontext): - interp = interpreter.Interpreter() - scheduler = wrapper.scheduler() + interp = interpreter.Interpreter(space) + scheduler = wrapper.scheduler(space) sleeping = new_process(priority=sleepingpriority, w_suspended_context=sleepingcontext) sleeping.put_to_sleep() @@ -181,79 +183,79 @@ def test_activate(self): - interp, process, old_process = self.make_processes(4, 2, objtable.w_false, objtable.w_true) + interp, process, old_process = self.make_processes(4, 2, space.w_false, space.w_true) process.activate(interp) self.new_process_consistency(process, old_process, interp, - objtable.w_true, objtable.w_false) + space.w_true, space.w_false) def test_resume(self): - interp, process, old_process = self.make_processes(4, 2, objtable.w_false, objtable.w_true) + interp, process, old_process = self.make_processes(4, 2, space.w_false, space.w_true) process.resume(interp) self.new_process_consistency(process, old_process, interp, - objtable.w_true, objtable.w_false) - self.old_process_consistency(old_process, objtable.w_true) + space.w_true, space.w_false) + self.old_process_consistency(old_process, space.w_true) # Does not reactivate old_process because lower priority old_process.resume(interp) self.new_process_consistency(process, old_process, interp, - objtable.w_true, objtable.w_false) - self.old_process_consistency(old_process, objtable.w_true) + space.w_true, space.w_false) + self.old_process_consistency(old_process, space.w_true) def test_semaphore_excess_signal(self): semaphore = new_semaphore() semaphore.signal(None) - assert utility.unwrap_int(semaphore.excess_signals()) == 1 + assert space.unwrap_int(semaphore.excess_signals()) == 1 def test_highest_priority(self): - py.test.raises(FatalError, wrapper.scheduler().highest_priority_process) - interp, process, old_process = self.make_processes(4, 2, objtable.w_false, objtable.w_true) + py.test.raises(FatalError, wrapper.scheduler(space).highest_priority_process) + interp, process, old_process = self.make_processes(4, 2, space.w_false, space.w_true) process.put_to_sleep() old_process.put_to_sleep() - highest = wrapper.scheduler().highest_priority_process() + highest = wrapper.scheduler(space).highest_priority_process() assert highest is process.w_self - highest = wrapper.scheduler().highest_priority_process() + highest = wrapper.scheduler(space).highest_priority_process() assert highest is old_process.w_self - py.test.raises(FatalError, wrapper.scheduler().highest_priority_process) + py.test.raises(FatalError, wrapper.scheduler(space).highest_priority_process) def test_semaphore_wait(self): semaphore = new_semaphore() - interp, process, old_process = self.make_processes(4, 2, objtable.w_false, objtable.w_true) + interp, process, old_process = self.make_processes(4, 2, space.w_false, space.w_true) semaphore.wait(interp) assert semaphore.first_link() is old_process.w_self - assert wrapper.scheduler().active_process() is process.w_self + assert wrapper.scheduler(space).active_process() is process.w_self def test_semaphore_signal_wait(self): semaphore = new_semaphore() semaphore.signal(None) - interp, process, old_process = self.make_processes(4, 2, objtable.w_false, objtable.w_true) + interp, process, old_process = self.make_processes(4, 2, space.w_false, space.w_true) semaphore.wait(interp) assert semaphore.is_empty_list() - assert wrapper.scheduler().active_process() is old_process.w_self + assert wrapper.scheduler(space).active_process() is old_process.w_self semaphore.wait(interp) assert semaphore.first_link() is old_process.w_self - assert wrapper.scheduler().active_process() is process.w_self + assert wrapper.scheduler(space).active_process() is process.w_self py.test.raises(FatalError, semaphore.wait, interp) def test_semaphore_wait_signal(self): semaphore = new_semaphore() - interp, process, old_process = self.make_processes(4, 2, objtable.w_false, objtable.w_true) + interp, process, old_process = self.make_processes(4, 2, space.w_false, space.w_true) semaphore.wait(interp) - assert wrapper.scheduler().active_process() is process.w_self + assert wrapper.scheduler(space).active_process() is process.w_self semaphore.signal(interp) - assert wrapper.scheduler().active_process() is process.w_self - process_list = wrapper.scheduler().get_process_list(old_process.priority()) + assert wrapper.scheduler(space).active_process() is process.w_self + process_list = wrapper.scheduler(space).get_process_list(old_process.priority()) assert process_list.remove_first_link_of_list() is old_process.w_self - process.write(2, utility.wrap_int(1)) + process.write(2, space.wrap_int(1)) old_process.resume(interp) - assert wrapper.scheduler().active_process() is old_process.w_self + assert wrapper.scheduler(space).active_process() is old_process.w_self semaphore.wait(interp) - assert wrapper.scheduler().active_process() is process.w_self + assert wrapper.scheduler(space).active_process() is process.w_self semaphore.signal(interp) - assert wrapper.scheduler().active_process() is old_process.w_self + assert wrapper.scheduler(space).active_process() is old_process.w_self - process_list = wrapper.scheduler().get_process_list(process.priority()) + process_list = wrapper.scheduler(space).get_process_list(process.priority()) assert process_list.first_link() is process.w_self Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/wrapper.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/wrapper.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/wrapper.py Sun May 25 16:09:07 2008 @@ -1,12 +1,12 @@ from pypy.lang.smalltalk import model -from pypy.lang.smalltalk import utility, objtable from pypy.lang.smalltalk.error import FatalError, WrapperException class Wrapper(object): - def __init__(self, w_self): + def __init__(self, space, w_self): if not isinstance(w_self, model.W_PointersObject): raise WrapperException("Unexpected instance given to wrapper") self.w_self = w_self + self.space = space def read(self, index0): try: @@ -42,29 +42,28 @@ def priority(self): w_priority = self.read(2) - return utility.unwrap_int(w_priority) + return self.space.unwrap_int(w_priority) def put_to_sleep(self): - sched = scheduler() + sched = scheduler(self.space) priority = self.priority() process_list = sched.get_process_list(priority) process_list.add_process(self.w_self) def activate(self, interp): - from pypy.lang.smalltalk import objtable - sched = scheduler() + sched = scheduler(self.space) sched.store_active_process(self.w_self) interp.store_w_active_context(self.suspended_context()) - self.store_suspended_context(objtable.w_nil) - self.store_my_list(objtable.w_nil) + self.store_suspended_context(interp.space.w_nil) + self.store_my_list(interp.space.w_nil) def deactivate(self, interp): self.put_to_sleep() self.store_suspended_context(interp.w_active_context()) def resume(self, interp): - sched = scheduler() - active_process = ProcessWrapper(sched.active_process()) + sched = scheduler(self.space) + active_process = ProcessWrapper(self.space, sched.active_process()) active_priority = active_process.priority() priority = self.priority() if priority > active_priority: @@ -74,43 +73,42 @@ self.put_to_sleep() def is_active_process(self): - return self.w_self.is_same_object(scheduler().active_process()) + return self.w_self.is_same_object(scheduler(self.space).active_process()) def suspend(self, interp): if self.is_active_process(): - assert self.my_list() is objtable.w_nil - ProcessWrapper(scheduler().highest_priority_process()).activate(interp) + assert self.my_list() is interp.space.w_nil + w_process = scheduler(self.space).highest_priority_process() + process = ProcessWrapper(self.space, w_process).activate(interp) else: - process_list = ProcessListWrapper(self.my_list()) + process_list = ProcessListWrapper(self.space, self.my_list()) process_list.remove(self.w_self) - self.store_my_list(objtable.w_nil) + self.store_my_list(interp.space.w_nil) class LinkedListWrapper(Wrapper): first_link, store_first_link = make_getter_setter(0) last_link, store_last_link = make_getter_setter(1) def is_empty_list(self): - from pypy.lang.smalltalk import objtable - return self.first_link() is objtable.w_nil + return self.first_link() is self.space.w_nil def add_last_link(self, w_object): if self.is_empty_list(): self.store_first_link(w_object) else: - LinkWrapper(self.last_link()).store_next_link(w_object) + LinkWrapper(self.space, self.last_link()).store_next_link(w_object) self.store_last_link(w_object) def remove_first_link_of_list(self): - from pypy.lang.smalltalk import objtable w_first = self.first_link() w_last = self.last_link() if w_first.is_same_object(w_last): - self.store_first_link(objtable.w_nil) - self.store_last_link(objtable.w_nil) + self.store_first_link(self.space.w_nil) + self.store_last_link(self.space.w_nil) else: - w_next = LinkWrapper(w_first).next_link() + w_next = LinkWrapper(self.space, w_first).next_link() self.store_first_link(w_next) - LinkWrapper(w_first).store_next_link(objtable.w_nil) + LinkWrapper(self.space, w_first).store_next_link(self.space.w_nil) return w_first def remove(self, w_link): @@ -118,24 +116,24 @@ self.remove_first_link_of_list() return else: - current = LinkWrapper(self.first_link()) + current = LinkWrapper(self.space, self.first_link()) w_next = current.next_link() - while not w_next.is_same_object(objtable.w_nil): + while not w_next.is_same_object(self.space.w_nil): if w_next.is_same_object(w_link): - LinkWrapper(w_link).store_next_link(objtable.w_nil) - w_tail = LinkWrapper(w_next).next_link() + LinkWrapper(self.space, w_link).store_next_link(self.space.w_nil) + w_tail = LinkWrapper(self.space, w_next).next_link() current.store_next_link(w_tail) - if w_tail.is_same_object(objtable.w_nil): + if w_tail.is_same_object(self.space.w_nil): self.store_last_link(current.w_self) return - current = LinkWrapper(w_next) + current = LinkWrapper(self.space, w_next) w_next = current.next_link() raise WrapperException("Could not find link") class ProcessListWrapper(LinkedListWrapper): def add_process(self, w_process): self.add_last_link(w_process) - ProcessWrapper(w_process).store_my_list(self.w_self) + ProcessWrapper(self.space, w_process).store_my_list(self.w_self) class AssociationWrapper(Wrapper): key = make_getter(0) @@ -146,28 +144,28 @@ active_process, store_active_process = make_getter_setter(1) def get_process_list(self, priority): - lists = self.priority_list() - return ProcessListWrapper(Wrapper(lists).read(priority)) + lists = Wrapper(self.space, self.priority_list()) + + return ProcessListWrapper(self.space, lists.read(priority)) def highest_priority_process(self): w_lists = self.priority_list() # Asserts as W_PointersObject - lists = Wrapper(w_lists) + lists = Wrapper(self.space, w_lists) for i in range(w_lists.size() - 1, -1, -1): - process_list = ProcessListWrapper(lists.read(i)) + process_list = ProcessListWrapper(self.space, lists.read(i)) if not process_list.is_empty_list(): return process_list.remove_first_link_of_list() raise FatalError("Scheduler could not find a runnable process") -def scheduler(): - from pypy.lang.smalltalk import objtable - w_association = objtable.get_objtable()["w_schedulerassociationpointer"] +def scheduler(space): + w_association = space.objtable["w_schedulerassociationpointer"] assert w_association is not None - w_scheduler = AssociationWrapper(w_association).value() + w_scheduler = AssociationWrapper(space, w_association).value() assert isinstance(w_scheduler, model.W_PointersObject) - return SchedulerWrapper(w_scheduler) + return SchedulerWrapper(space, w_scheduler) class SemaphoreWrapper(LinkedListWrapper): @@ -176,17 +174,18 @@ def signal(self, interp): if self.is_empty_list(): w_value = self.excess_signals() - w_value = utility.wrap_int(utility.unwrap_int(w_value) + 1) + w_value = self.space.wrap_int(self.space.unwrap_int(w_value) + 1) self.store_excess_signals(w_value) else: - ProcessWrapper(self.remove_first_link_of_list()).resume(interp) + process = self.remove_first_link_of_list() + ProcessWrapper(self.space, process).resume(interp) def wait(self, interp): - excess = utility.unwrap_int(self.excess_signals()) - w_process = scheduler().active_process() + excess = self.space.unwrap_int(self.excess_signals()) + w_process = scheduler(interp.space).active_process() if excess > 0: - w_excess = utility.wrap_int(excess - 1) + w_excess = self.space.wrap_int(excess - 1) self.store_excess_signals(w_excess) else: self.add_last_link(w_process) - ProcessWrapper(w_process).suspend(interp) + ProcessWrapper(self.space, w_process).suspend(interp) From cfbolz at codespeak.net Sun May 25 16:27:39 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sun, 25 May 2008 16:27:39 +0200 (CEST) Subject: [pypy-svn] r55205 - in pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk: . test Message-ID: <20080525142739.9C510169E97@codespeak.net> Author: cfbolz Date: Sun May 25 16:27:37 2008 New Revision: 55205 Added: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/objspace.py - copied unchanged from r55204, pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/space.py Removed: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/space.py Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_interpreter.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_miniimage.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_model.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_objectspace.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_primitives.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_shadow.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_squeakimage.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_wrapper.py Log: rename module Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_interpreter.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_interpreter.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_interpreter.py Sun May 25 16:27:37 2008 @@ -1,6 +1,6 @@ import py from pypy.lang.smalltalk import model, interpreter, primitives, shadow -from pypy.lang.smalltalk import space as objspace +from pypy.lang.smalltalk import objspace mockclass = objspace.bootstrap_class Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_miniimage.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_miniimage.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_miniimage.py Sun May 25 16:27:37 2008 @@ -7,7 +7,7 @@ from pypy.lang.smalltalk import constants from pypy.lang.smalltalk import interpreter from pypy.lang.smalltalk import shadow -from pypy.lang.smalltalk import space as objspace +from pypy.lang.smalltalk import objspace # lazy initialization of test data, ie ImageReader and Float class def setup_module(module, filename='mini.image'): Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_model.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_model.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_model.py Sun May 25 16:27:37 2008 @@ -1,7 +1,7 @@ import py from pypy.lang.smalltalk import model, shadow from pypy.lang.smalltalk.shadow import MethodNotFound -from pypy.lang.smalltalk import space as objspace +from pypy.lang.smalltalk import objspace mockclass = objspace.bootstrap_class Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_objectspace.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_objectspace.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_objectspace.py Sun May 25 16:27:37 2008 @@ -1,4 +1,4 @@ -from pypy.lang.smalltalk import space as objspace +from pypy.lang.smalltalk import objspace space = objspace.ObjSpace() Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_primitives.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_primitives.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_primitives.py Sun May 25 16:27:37 2008 @@ -5,7 +5,7 @@ from pypy.lang.smalltalk import constants from pypy.rlib.rarithmetic import INFINITY, NAN, isinf, isnan from pypy.lang.smalltalk import primitives -from pypy.lang.smalltalk import space as objspace +from pypy.lang.smalltalk import objspace mockclass = objspace.bootstrap_class Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_shadow.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_shadow.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_shadow.py Sun May 25 16:27:37 2008 @@ -1,6 +1,6 @@ import random from pypy.lang.smalltalk import model, shadow, constants -from pypy.lang.smalltalk import space as objspace +from pypy.lang.smalltalk import objspace space = objspace.ObjSpace() Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_squeakimage.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_squeakimage.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_squeakimage.py Sun May 25 16:27:37 2008 @@ -1,7 +1,7 @@ import py from pypy.lang.smalltalk import squeakimage from pypy.lang.smalltalk.squeakimage import chrs2int -from pypy.lang.smalltalk import space as objspace +from pypy.lang.smalltalk import objspace space = objspace.ObjSpace() Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_wrapper.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_wrapper.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_wrapper.py Sun May 25 16:27:37 2008 @@ -3,7 +3,7 @@ from pypy.lang.smalltalk import model from pypy.lang.smalltalk import interpreter from pypy.lang.smalltalk.error import WrapperException, FatalError -from pypy.lang.smalltalk import space as objspace +from pypy.lang.smalltalk import objspace space = objspace.ObjSpace() From cfbolz at codespeak.net Sun May 25 17:06:48 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sun, 25 May 2008 17:06:48 +0200 (CEST) Subject: [pypy-svn] r55206 - in pypy/branch/smalltalk-shadow-changes/pypy: lang/smalltalk/tool translator/goal Message-ID: <20080525150648.84DE8698059@codespeak.net> Author: cfbolz Date: Sun May 25 17:06:46 2008 New Revision: 55206 Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/tool/analyseimage.py pypy/branch/smalltalk-shadow-changes/pypy/translator/goal/targettinybenchsmalltalk.py Log: fix first image Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/tool/analyseimage.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/tool/analyseimage.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/tool/analyseimage.py Sun May 25 17:06:46 2008 @@ -3,22 +3,20 @@ from pypy.lang.smalltalk import squeakimage from pypy.lang.smalltalk import constants from pypy.lang.smalltalk import model -from pypy.lang.smalltalk import objtable -from pypy.lang.smalltalk import classtable from pypy.lang.smalltalk import interpreter import sys mini_image = py.magic.autopath().dirpath().dirpath().join('mini.image') -def get_miniimage(): - return squeakimage.ImageReader(squeakimage.Stream(mini_image.open())) +def get_miniimage(space): + return squeakimage.ImageReader(space, squeakimage.Stream(mini_image.open())) -def create_squeakimage(): - example = get_miniimage() +def create_squeakimage(space): + example = get_miniimage(space) example.initialize() image = squeakimage.SqueakImage() - image.from_reader(example) + image.from_reader(space, example) return image def printStringsInImage(): Modified: pypy/branch/smalltalk-shadow-changes/pypy/translator/goal/targettinybenchsmalltalk.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/translator/goal/targettinybenchsmalltalk.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/translator/goal/targettinybenchsmalltalk.py Sun May 25 17:06:46 2008 @@ -1,9 +1,6 @@ -import os -from pypy.lang.smalltalk import model, interpreter, primitives, shadow -from pypy.lang.smalltalk import objtable -from pypy.lang.smalltalk.utility import wrap_int -from pypy.lang.smalltalk import classtable -from pypy.lang.smalltalk.tool.analyseimage import * +import os, sys +from pypy.lang.smalltalk import model, interpreter, primitives, shadow, constants +from pypy.lang.smalltalk.tool.analyseimage import create_squeakimage # This loads the whole mini.image in advance. At run-time, # it executes the tinyBenchmark. In this way we get an RPython @@ -18,18 +15,20 @@ def tinyBenchmarks(): - image = create_squeakimage() - interp = interpreter.Interpreter() + from pypy.lang.smalltalk import objspace + space = objspace.ObjSpace() + image = create_squeakimage(space) + interp = interpreter.Interpreter(space) w_object = model.W_SmallInteger(0) # Should get this from w_object w_smallint_class = image.special(constants.SO_SMALLINTEGER_CLASS) - s_class = w_object.shadow_of_my_class() + s_class = w_object.shadow_of_my_class(space) w_method = s_class.lookup("tinyBenchmarks") assert w_method - w_frame = w_method.create_frame(w_object, []) + w_frame = w_method.create_frame(space, w_object, []) interp.store_w_active_context(w_frame) counter = 0 From cfbolz at codespeak.net Sun May 25 17:22:40 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sun, 25 May 2008 17:22:40 +0200 (CEST) Subject: [pypy-svn] r55207 - in pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk: . test Message-ID: <20080525152240.371A1169F01@codespeak.net> Author: cfbolz Date: Sun May 25 17:22:38 2008 New Revision: 55207 Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/interpreter.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/objspace.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/primitives.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_interpreter.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_miniimage.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_model.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_primitives.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_shadow.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/wrapper.py Log: humpf, fetch and store need a space as well Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/interpreter.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/interpreter.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/interpreter.py Sun May 25 17:22:38 2008 @@ -100,7 +100,7 @@ # push bytecodes def pushReceiverVariableBytecode(self, interp): index = self.currentBytecode & 15 - self.push(self.w_receiver().fetch(index)) + self.push(self.w_receiver().fetch(self.space, index)) def pushTemporaryVariableBytecode(self, interp): index = self.currentBytecode & 15 @@ -121,7 +121,7 @@ def storeAndPopReceiverVariableBytecode(self, interp): index = self.currentBytecode & 7 - self.w_receiver().store(index, self.pop()) + self.w_receiver().store(self.space, index, self.pop()) def storeAndPopTemporaryVariableBytecode(self, interp): index = self.currentBytecode & 7 @@ -252,7 +252,7 @@ def extendedPushBytecode(self, interp): variableType, variableIndex = self.extendedVariableTypeAndIndex() if variableType == 0: - self.push(self.w_receiver().fetch(variableIndex)) + self.push(self.w_receiver().fetch(self.space, variableIndex)) elif variableType == 1: self.push(self.gettemp(variableIndex)) elif variableType == 2: @@ -267,7 +267,7 @@ def extendedStoreBytecode(self, interp): variableType, variableIndex = self.extendedVariableTypeAndIndex() if variableType == 0: - self.w_receiver().store(variableIndex, self.top()) + self.w_receiver().store(self.space, variableIndex, self.top()) elif variableType == 1: self.settemp(variableIndex, self.top()) elif variableType == 2: @@ -304,7 +304,7 @@ second & 31, interp) elif opType == 2: # pushReceiver - self.push(self.w_receiver().fetch(third)) + self.push(self.w_receiver().fetch(self.space, third)) elif opType == 3: # pushLiteralConstant self.push(self.w_method().getliteral(third)) @@ -314,9 +314,9 @@ association = wrapper.AssociationWrapper(self.space, w_association) self.push(association.value()) elif opType == 5: - self.w_receiver().store(third, self.top()) + self.w_receiver().store(self.space, third, self.top()) elif opType == 6: - self.w_receiver().store(third, self.pop()) + self.w_receiver().store(self.space, third, self.pop()) elif opType == 7: w_association = self.w_method().getliteral(third) association = wrapper.AssociationWrapper(self.space, w_association) Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py Sun May 25 17:22:38 2008 @@ -69,13 +69,13 @@ otherwise patches bytecode (ie byte code indexing starts at literalsize).""" raise NotImplementedError() - def fetch(self, n0): + def fetch(self, space, n0): """Access fixed-size part, maybe also variable-sized part (we have to consult the Blue Book).""" # TODO check the Blue Book raise NotImplementedError() - def store(self, n0, w_value): + def store(self, space, n0, w_value): """Access fixed-size part, maybe also variable-sized part (we have to consult the Blue Book).""" raise NotImplementedError() @@ -245,13 +245,13 @@ def at0(self, space, index0): # To test, at0 = in varsize part - return self.fetch(index0+self.instsize(space)) + return self.fetch(space, index0+self.instsize(space)) def atput0(self, space, index0, w_value): # To test, at0 = in varsize part - self.store(index0+self.instsize(space), w_value) + self.store(space, index0 + self.instsize(space), w_value) - def fetch(self, n0): + def fetch(self, space, n0): if self._shadow is not None: return self._shadow.fetch(n0) return self._fetch(n0) @@ -259,7 +259,7 @@ def _fetch(self, n0): return self._vars[n0] - def store(self, n0, w_value): + def store(self, space, n0, w_value): if self._shadow is not None: return self._shadow.store(n0, w_value) return self._store(n0, w_value) @@ -267,11 +267,6 @@ def _store(self, n0, w_value): self._vars[n0] = w_value - # def fetchvarpointer(self, idx): - # return self._vars[idx+self.instsize()] - - # def storevarpointer(self, idx, value): - # self._vars[idx+self.instsize()] = value def varsize(self, space): return self.size() - self.instsize(space) @@ -552,8 +547,8 @@ else: self.literals[index0-1] = w_value - def store(self, index0, w_v): - self.atput0(index0, w_v) + def store(self, space, index0, w_v): + self.atput0(space, index0, w_v) def at0(self, space, index0): if index0 <= self.getliteralsize(): Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/objspace.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/objspace.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/objspace.py Sun May 25 17:22:38 2008 @@ -120,7 +120,7 @@ def make_bootstrap_objects(self): def bld_char(i): w_cinst = self.w_Character.as_class_get_shadow(self).new() - w_cinst.store(constants.CHARACTER_VALUE_INDEX, + w_cinst.store(self, constants.CHARACTER_VALUE_INDEX, model.W_SmallInteger(i)) return w_cinst w_charactertable = model.W_PointersObject( @@ -171,7 +171,7 @@ return w_inst def wrap_char(self, c): - return self.w_charactertable.fetch(ord(c)) + return self.w_charactertable.fetch(self, ord(c)) def wrap_bool(self, b): if b: @@ -200,7 +200,7 @@ w_class = w_char.getclass(self) if not w_class.is_same_object(self.w_Character): raise UnwrappingError("expected character, got %s" % (w_class, )) - w_ord = w_char.fetch(constants.CHARACTER_VALUE_INDEX) + w_ord = w_char.fetch(self, constants.CHARACTER_VALUE_INDEX) w_class = w_ord.getclass(self) if not w_class.is_same_object(self.w_SmallInteger): raise UnwrappingError("expected smallint from character, got %s" % (w_class, )) Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/primitives.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/primitives.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/primitives.py Sun May 25 17:22:38 2008 @@ -395,7 +395,7 @@ # only pointers have non-0 size # XXX Now MethodContext is still own format, leave #assert isinstance(w_rcvr, model.W_PointersObject) - return w_rcvr.fetch(n0) + return w_rcvr.fetch(interp.space, n0) @expose_primitive(INST_VAR_AT_PUT, unwrap_spec=[object, index1_0, object]) def func(interp, w_rcvr, n0, w_value): @@ -404,7 +404,7 @@ assert_bounds(n0, 0, s_class.instsize()) # XXX Now MethodContext is still own format, leave #assert isinstance(w_rcvr, model.W_PointersObject) - w_rcvr.store(n0, w_value) + w_rcvr.store(interp.space, n0, w_value) return w_value @expose_primitive(AS_OOP, unwrap_spec=[object]) @@ -724,7 +724,7 @@ assert w_method w_frame = w_method.create_frame(interp.space, w_rcvr, - [w_args.fetch(i) for i in range(w_args.size())]) + [w_args.fetch(interp.space, i) for i in range(w_args.size())]) w_frame.as_context_get_shadow(interp.space).store_w_sender(interp.w_active_context()) interp.store_w_active_context(w_frame) @@ -785,7 +785,7 @@ def make_prim(i): @expose_primitive(i, unwrap_spec=[object]) def func(interp, w_object): - return w_object.fetch(i - 264) + return w_object.fetch(interp.space, i - 264) globals()["INST_VAR_AT_%d" % (i-264)] = i make_prim(i) Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py Sun May 25 17:22:38 2008 @@ -320,7 +320,7 @@ @staticmethod def is_block_context(w_pointers, space): - method_or_argc = w_pointers.fetch(constants.MTHDCTX_METHOD) + method_or_argc = w_pointers.fetch(space, constants.MTHDCTX_METHOD) return method_or_argc.getclass(space).is_same_object( space.w_SmallInteger) Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_interpreter.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_interpreter.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_interpreter.py Sun May 25 17:22:38 2008 @@ -128,9 +128,9 @@ pushReceiverVariableBytecode(1) + pushReceiverVariableBytecode(2))): w_demo = mockclass(space, 3).as_class_get_shadow(space).new() - w_demo.store(0, "egg") - w_demo.store(1, "bar") - w_demo.store(2, "baz") + w_demo.store(space, 0, "egg") + w_demo.store(space, 1, "bar") + w_demo.store(space, 2, "baz") interp = new_interpreter(bytecode, receiver = w_demo) interp.step() interp.step() @@ -161,8 +161,8 @@ def test_pushLiteralVariableBytecode(bytecode=pushLiteralVariableBytecode(0)): w_association = mockclass(space, 2).as_class_get_shadow(space).new() - w_association.store(0, "mykey") - w_association.store(1, "myvalue") + w_association.store(space, 0, "mykey") + w_association.store(space, 1, "myvalue") interp = new_interpreter(bytecode) interp.w_active_context().as_methodcontext_get_shadow(space).w_method().literals = fakeliterals(space, w_association) interp.step() @@ -184,9 +184,9 @@ for test_index in range(8): if test_index == index: - assert w_object.fetch(test_index).is_same_object(space.w_true) + assert w_object.fetch(space, test_index).is_same_object(space.w_true) else: - assert w_object.fetch(test_index) is space.w_nil + assert w_object.fetch(space, test_index) is space.w_nil def test_storeAndPopTemporaryVariableBytecode(bytecode=storeAndPopTemporaryVariableBytecode): for index in range(8): @@ -526,13 +526,13 @@ def storeAssociation(bytecode): w_association = mockclass(space, 2).as_class_get_shadow(space).new() - w_association.store(0, "mykey") - w_association.store(1, "myvalue") + w_association.store(space, 0, "mykey") + w_association.store(space, 1, "myvalue") interp = new_interpreter(pushConstantOneBytecode + bytecode) interp.w_active_context().as_methodcontext_get_shadow(space).w_method().literals = fakeliterals(space, w_association) interp.step() interp.step() - assert w_association.fetch(1).is_same_object(space.w_one) + assert w_association.fetch(space, 1).is_same_object(space.w_one) def test_extendedStoreAndPopBytecode(): test_storeAndPopReceiverVariableBytecode(lambda index: extendedStoreAndPopBytecode + chr((0<<6) + index)) @@ -754,8 +754,8 @@ # ^ self at: 1 w_fakeclass = mockclass(space, 1, name='fakeclass', varsized=True) w_fakeinst = w_fakeclass.as_class_get_shadow(space).new(1) - w_fakeinst.store(0, space.wrap_char("a")) # static slot 0: instance variable - w_fakeinst.store(1, space.wrap_char("b")) # varying slot 1 + w_fakeinst.store(space, 0, space.wrap_char("a")) # static slot 0: instance variable + w_fakeinst.store(space, 1, space.wrap_char("b")) # varying slot 1 def test(): assert space.unwrap_char(interpret_bc( [112, 118, 192, 124], @@ -769,15 +769,15 @@ # ^ self at: 1 put: #b w_fakeclass = mockclass(space, 1, name='fakeclass', varsized=True) w_fakeinst = w_fakeclass.as_class_get_shadow(space).new(1) - w_fakeinst.store(0, space.wrap_char("a")) # static slot 0: instance variable - w_fakeinst.store(1, space.wrap_char("a")) # varying slot 1 + w_fakeinst.store(space, 0, space.wrap_char("a")) # static slot 0: instance variable + w_fakeinst.store(space, 1, space.wrap_char("a")) # varying slot 1 def test(): assert space.unwrap_char(interpret_bc( [0x70, 0x76, 0x20, 0xc1, 0x7c], fakeliterals(space, space.wrap_char("b")), receiver=w_fakeinst)) == "b" - assert space.unwrap_char(w_fakeinst.fetch(0)) == "a" - assert space.unwrap_char(w_fakeinst.fetch(1)) == "b" + assert space.unwrap_char(w_fakeinst.fetch(space, 0)) == "a" + assert space.unwrap_char(w_fakeinst.fetch(space, 1)) == "b" run_with_faked_methods( [[w_fakeclass, primitives.AT_PUT, 2, "at:put:"]], test) Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_miniimage.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_miniimage.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_miniimage.py Sun May 25 17:22:38 2008 @@ -70,7 +70,7 @@ def test_float_class_name(): w_float_class = get_float_class() - w_float_class_name = w_float_class.fetch(6) + w_float_class_name = w_float_class.fetch(space, 6) assert isinstance(w_float_class_name, model.W_BytesObject) assert w_float_class_name.bytes == list("Float") @@ -98,9 +98,9 @@ def test_scheduler(): image = get_image() w = image.special(constants.SO_SCHEDULERASSOCIATIONPOINTER) - w0 = w.fetch(0) + w0 = w.fetch(space, 0) assert str(w0) == "Processor" - w0 = w.fetch(1) + w0 = w.fetch(space, 1) w0.shadow_of_my_class(space) assert str(w0) == "a ProcessorScheduler" Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_model.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_model.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_model.py Sun May 25 17:22:38 2008 @@ -27,10 +27,10 @@ w_myinstance = w_mycls.as_class_get_shadow(space).new() assert isinstance(w_myinstance, model.W_PointersObject) assert w_myinstance.getclass(space).is_same_object(w_mycls) - assert w_myinstance.fetch(0) is space.w_nil - py.test.raises(IndexError, lambda: w_myinstance.fetch(3)) - w_myinstance.store(1, w_myinstance) - assert w_myinstance.fetch(1) is w_myinstance + assert w_myinstance.fetch(space, 0) is space.w_nil + py.test.raises(IndexError, lambda: w_myinstance.fetch(space, 3)) + w_myinstance.store(space, 1, w_myinstance) + assert w_myinstance.fetch(space, 1) is w_myinstance def test_bytes_object(): w_class = mockclass(space, 0, format=shadow.BYTES) @@ -176,8 +176,8 @@ hasha = w_a.gethash() hashb = w_b.gethash() - w_a.store(0, w_b) - w_b.store(1, w_a) + w_a.store(space, 0, w_b) + w_b.store(space, 1, w_a) res = w_a.become(w_b) assert res @@ -187,8 +187,8 @@ assert w_a.getclass(space).is_same_object(w_clsb) assert w_b.getclass(space).is_same_object(w_clsa) - assert w_b.fetch(0) is w_b - assert w_a.fetch(1) is w_a + assert w_b.fetch(space, 0) is w_b + assert w_a.fetch(space, 1) is w_a def test_become_with_shadow(): w_clsa = mockclass(space, 3) Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_primitives.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_primitives.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_primitives.py Sun May 25 17:22:38 2008 @@ -184,7 +184,7 @@ def test_at(): w_obj = mockclass(space, 0, varsized=True).as_class_get_shadow(space).new(1) - w_obj.store(0, "foo") + w_obj.store(space, 0, "foo") assert prim(primitives.AT, [w_obj, 1]) == "foo" def test_invalid_at(): Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_shadow.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_shadow.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_shadow.py Sun May 25 17:22:38 2008 @@ -14,18 +14,18 @@ w_methoddict = w_MethodDict.as_class_get_shadow(space).new(size) w_array = w_Array.as_class_get_shadow(space).new(size) for i in range(size): - w_array.store(i, space.w_nil) - w_methoddict.store(constants.METHODDICT_NAMES_INDEX+i, space.w_nil) + w_array.store(space, i, space.w_nil) + w_methoddict.store(space, constants.METHODDICT_NAMES_INDEX+i, space.w_nil) w_tally = space.wrap_int(len(methods)) - w_methoddict.store(constants.METHODDICT_TALLY_INDEX, w_tally) - w_methoddict.store(constants.METHODDICT_VALUES_INDEX, w_array) + w_methoddict.store(space, constants.METHODDICT_TALLY_INDEX, w_tally) + w_methoddict.store(space, constants.METHODDICT_VALUES_INDEX, w_array) positions = range(size) random.shuffle(positions) for selector, w_compiledmethod in methods.items(): pos = positions.pop() w_selector = space.wrap_string(selector) - w_methoddict.store(constants.METHODDICT_NAMES_INDEX+pos, w_selector) - w_array.store(pos, w_compiledmethod) + w_methoddict.store(space, constants.METHODDICT_NAMES_INDEX+pos, w_selector) + w_array.store(space, pos, w_compiledmethod) return w_methoddict def build_smalltalk_class(name, format, w_superclass=w_Object, @@ -37,11 +37,11 @@ w_methoddict = build_methoddict(methods) size = constants.CLASS_NAME_INDEX + 1 w_class = model.W_PointersObject(w_classofclass, size) - w_class.store(constants.CLASS_SUPERCLASS_INDEX, w_superclass) - w_class.store(constants.CLASS_METHODDICT_INDEX, w_methoddict) - w_class.store(constants.CLASS_FORMAT_INDEX, space.wrap_int(format)) + w_class.store(space, constants.CLASS_SUPERCLASS_INDEX, w_superclass) + w_class.store(space, constants.CLASS_METHODDICT_INDEX, w_methoddict) + w_class.store(space, constants.CLASS_FORMAT_INDEX, space.wrap_int(format)) if name is not None: - w_class.store(constants.CLASS_NAME_INDEX, space.wrap_string(name)) + w_class.store(space, constants.CLASS_NAME_INDEX, space.wrap_string(name)) return w_class def basicshape(name, format, kind, varsized, instsize): @@ -82,27 +82,27 @@ def methodcontext(w_sender=space.w_nil, pc=1, stackpointer=0, stacksize=5, method=method()): w_object = model.W_PointersObject(space.w_MethodContext, constants.MTHDCTX_TEMP_FRAME_START+method.tempsize+stacksize) - w_object.store(constants.CTXPART_SENDER_INDEX, w_sender) - w_object.store(constants.CTXPART_PC_INDEX, space.wrap_int(pc)) - w_object.store(constants.CTXPART_STACKP_INDEX, space.wrap_int(method.tempsize+stackpointer)) - w_object.store(constants.MTHDCTX_METHOD, method) + w_object.store(space, constants.CTXPART_SENDER_INDEX, w_sender) + w_object.store(space, constants.CTXPART_PC_INDEX, space.wrap_int(pc)) + w_object.store(space, constants.CTXPART_STACKP_INDEX, space.wrap_int(method.tempsize+stackpointer)) + w_object.store(space, constants.MTHDCTX_METHOD, method) # XXX - w_object.store(constants.MTHDCTX_RECEIVER_MAP, '???') - w_object.store(constants.MTHDCTX_RECEIVER, 'receiver') + w_object.store(space, constants.MTHDCTX_RECEIVER_MAP, '???') + w_object.store(space, constants.MTHDCTX_RECEIVER, 'receiver') - w_object.store(constants.MTHDCTX_TEMP_FRAME_START, 'el') + w_object.store(space, constants.MTHDCTX_TEMP_FRAME_START, 'el') return w_object def blockcontext(w_sender=space.w_nil, pc=1, stackpointer=1, stacksize=5, home=methodcontext()): w_object = model.W_PointersObject(space.w_MethodContext, constants.MTHDCTX_TEMP_FRAME_START+stacksize) - w_object.store(constants.CTXPART_SENDER_INDEX, w_sender) - w_object.store(constants.CTXPART_PC_INDEX, space.wrap_int(pc)) - w_object.store(constants.CTXPART_STACKP_INDEX, space.wrap_int(stackpointer)) - w_object.store(constants.BLKCTX_BLOCK_ARGUMENT_COUNT_INDEX, space.wrap_int(54)) - w_object.store(constants.BLKCTX_INITIAL_IP_INDEX, space.wrap_int(17)) - w_object.store(constants.BLKCTX_HOME_INDEX, home) - w_object.store(constants.BLKCTX_STACK_START, 'el') + w_object.store(space, constants.CTXPART_SENDER_INDEX, w_sender) + w_object.store(space, constants.CTXPART_PC_INDEX, space.wrap_int(pc)) + w_object.store(space, constants.CTXPART_STACKP_INDEX, space.wrap_int(stackpointer)) + w_object.store(space, constants.BLKCTX_BLOCK_ARGUMENT_COUNT_INDEX, space.wrap_int(54)) + w_object.store(space, constants.BLKCTX_INITIAL_IP_INDEX, space.wrap_int(17)) + w_object.store(space, constants.BLKCTX_HOME_INDEX, home) + w_object.store(space, constants.BLKCTX_STACK_START, 'el') return w_object def test_context(): @@ -112,7 +112,7 @@ s_object = w_object.as_methodcontext_get_shadow(space) assert len(s_object.stack()) == 3 s_object2 = w_object2.as_methodcontext_get_shadow(space) - assert w_object2.fetch(constants.CTXPART_SENDER_INDEX) == w_object + assert w_object2.fetch(space, constants.CTXPART_SENDER_INDEX) == w_object assert s_object.w_self() == w_object assert s_object2.w_self() == w_object2 assert s_object.s_sender() == None @@ -124,9 +124,9 @@ assert s_object2.gettemp(0) == 'a' assert s_object.w_method() == w_m idx = s_object.stackstart() - w_object.store(idx, 'f') - w_object.store(idx + 1, 'g') - w_object.store(idx + 2, 'h') + w_object.store(space, idx, 'f') + w_object.store(space, idx + 1, 'g') + w_object.store(space, idx + 2, 'h') assert s_object.stack() == ['f', 'g', 'h' ] assert s_object.top() == 'h' s_object.push('i') Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/wrapper.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/wrapper.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/wrapper.py Sun May 25 17:22:38 2008 @@ -10,13 +10,13 @@ def read(self, index0): try: - return self.w_self.fetch(index0) + return self.w_self.fetch(self.space, index0) except IndexError: raise WrapperException("Unexpected instance layout. Too small") def write(self, index0, w_new): try: - self.w_self.store(index0, w_new) + self.w_self.store(self.space, index0, w_new) except IndexError: raise WrapperException("Unexpected instance layout. Too small") From cfbolz at codespeak.net Sun May 25 18:04:45 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sun, 25 May 2008 18:04:45 +0200 (CEST) Subject: [pypy-svn] r55208 - pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk Message-ID: <20080525160445.39E3B169E33@codespeak.net> Author: cfbolz Date: Sun May 25 18:04:42 2008 New Revision: 55208 Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py Log: attach a default name of None Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/shadow.py Sun May 25 18:04:42 2008 @@ -76,6 +76,7 @@ """A shadow for Smalltalk objects that are classes (i.e. used as the class of another Smalltalk object). """ + name = None def __init__(self, space, w_self): self.name = "" AbstractCachingShadow.__init__(self, space, w_self) From cami at codespeak.net Sun May 25 19:42:00 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Sun, 25 May 2008 19:42:00 +0200 (CEST) Subject: [pypy-svn] r55210 - pypy/dist/pypy/lang/gameboy Message-ID: <20080525174200.D1B14169F08@codespeak.net> Author: cami Date: Sun May 25 19:42:00 2008 New Revision: 55210 Modified: pypy/dist/pypy/lang/gameboy/cartridge.py pypy/dist/pypy/lang/gameboy/gameboyImplementation.py pypy/dist/pypy/lang/gameboy/video.py Log: small refactorings Modified: pypy/dist/pypy/lang/gameboy/cartridge.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/cartridge.py (original) +++ pypy/dist/pypy/lang/gameboy/cartridge.py Sun May 25 19:42:00 2008 @@ -501,7 +501,10 @@ elif address <= 0x7FFF: # 6000-7FFF self.write_clock_latch(address, data) elif address >= 0xA000 and address <= 0xBFFF and self.ram_enable: # A000-BFFF - self.write_clock_data(address, data) + if self.ram_bank >= 0: + self.ram[self.ram_bank + (address & 0x1FFF)] = data + else: + self.write_clock_data(address, data) def write_rom_bank(self, address, data): if data == 0: @@ -522,22 +525,18 @@ self.clock_latch = data def write_clock_data(self, address, data): - if self.ram_bank >= 0: - self.ram[self.ram_bank + (address & 0x1FFF)] = data - else: - self.update_clock() - if self.clock_register == 0x08: - self.clock_seconds = data - if self.clock_register == 0x09: - self.clock_minutes = data - if self.clock_register == 0x0A: - self.clock_hours = data - if self.clock_register == 0x0B: - self.clock_days = data - if self.clock_register == 0x0C: - self.clock_control = (self.clock_control & 0x80) | data + self.update_clock() + if self.clock_register == 0x08: + self.clock_seconds = data + if self.clock_register == 0x09: + self.clock_minutes = data + if self.clock_register == 0x0A: + self.clock_hours = data + if self.clock_register == 0x0B: + self.clock_days = data + if self.clock_register == 0x0C: + self.clock_control = (self.clock_control & 0x80) | data - def latch_clock(self): self.update_clock() self.clock_latched_seconds = self.clock_seconds @@ -546,7 +545,6 @@ self.clock_latched_days = self.clock_days & 0xFF self.clock_latched_control = (self.clock_control & 0xFE) | ((self.clock_days >> 8) & 0x01) - def update_clock(self): now = self.clock.get_time() if (self.clock_control & 0x40) == 0: @@ -600,7 +598,6 @@ MBC.reset(self) self.rumble = True - def write(self, address, data): address = int(address) if address <= 0x1FFF: # 0000-1FFF Modified: pypy/dist/pypy/lang/gameboy/gameboyImplementation.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/gameboyImplementation.py (original) +++ pypy/dist/pypy/lang/gameboy/gameboyImplementation.py Sun May 25 19:42:00 2008 @@ -196,30 +196,3 @@ # ============================================================================== - -ROM_PATH = str(py.magic.autopath().dirpath().dirpath().dirpath())+"/lang/gameboy/rom" -import pdb - -def entry_point(argv=None): - if argv is not None and len(argv) > 0: - filename = argv[0] - else: - pos = str(8) - filename = ROM_PATH+"/rom"+pos+"/rom"+pos+".gb" - print "loading rom: ", str(filename) - gameBoy = GameBoyImplementation() - gameBoy.load_cartridge_file(str(filename)) - gameBoy.mainLoop() - #pdb.runcall(gameBoy.mainLoop) - return 0 - - -# _____ Define and setup target ___ - -def target(*args): - return entry_point, None - -def test_target(): - entry_point() - - Modified: pypy/dist/pypy/lang/gameboy/video.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/video.py (original) +++ pypy/dist/pypy/lang/gameboy/video.py Sun May 25 19:42:00 2008 @@ -156,10 +156,10 @@ def read_oam(self, address): if (address >= constants.OAM_ADDR and \ - address < constants.OAM_ADDR + constants.OAM_SIZE): + address < constants.OAM_ADDR + constants.OAM_SIZE): return self.oam[address - constants.OAM_ADDR] elif (address >= constants.VRAM_ADDR and \ - address < constants.VRAM_ADDR + constants.VRAM_SIZE): + address < constants.VRAM_ADDR + constants.VRAM_SIZE): return self.vram[address - constants.VRAM_ADDR] return 0xFF @@ -562,8 +562,7 @@ self.line[x + i] = (pattern >> (7-i)) & 0x0101 def draw_object_tile(self, x, address, flags): - self.draw_object(set_tile_line_call_wrapper(self), x, address, \ - flags) + self.draw_object(set_tile_line_call_wrapper(self), x, address, flags) def set_tile_line(self, pos, color, mask): self.line[pos] |= color | mask From cami at codespeak.net Sun May 25 19:43:34 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Sun, 25 May 2008 19:43:34 +0200 (CEST) Subject: [pypy-svn] r55211 - pypy/dist/pypy/lang/gameboy Message-ID: <20080525174334.4875B698053@codespeak.net> Author: cami Date: Sun May 25 19:43:33 2008 New Revision: 55211 Added: pypy/dist/pypy/lang/gameboy/gameboyTest.py Log: test setup to run roms by commandline arguments Added: pypy/dist/pypy/lang/gameboy/gameboyTest.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/lang/gameboy/gameboyTest.py Sun May 25 19:43:33 2008 @@ -0,0 +1,23 @@ +from pypy.lang.gameboy.gameboyImplementation import * +import sys + +from AppKit import NSApplication +NSApplication.sharedApplication() + +filename = "" +if len(sys.argv) > 1: + print sys.argv + filename = sys.argv[1] +else: + pos = str(8) + filename = ROM_PATH+"/rom"+pos+"/rom"+pos+".gb" +print "loading rom: ", str(filename) +gameBoy = GameBoyImplementation() +try: + gameBoy.load_cartridge_file(str(filename)) +except: + print "Cartridge is Corrupted!" + +gameBoy.load_cartridge_file(str(filename), verify=False) +gameBoy.mainLoop() +#pdb.runcall(gameBoy.mainLoop) From cami at codespeak.net Sun May 25 19:47:08 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Sun, 25 May 2008 19:47:08 +0200 (CEST) Subject: [pypy-svn] r55212 - pypy/dist/pypy/lang/gameboy Message-ID: <20080525174708.A6C53698053@codespeak.net> Author: cami Date: Sun May 25 19:47:07 2008 New Revision: 55212 Modified: pypy/dist/pypy/lang/gameboy/gameboyTest.py Log: fixed rom path Modified: pypy/dist/pypy/lang/gameboy/gameboyTest.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/gameboyTest.py (original) +++ pypy/dist/pypy/lang/gameboy/gameboyTest.py Sun May 25 19:47:07 2008 @@ -4,6 +4,8 @@ from AppKit import NSApplication NSApplication.sharedApplication() +ROM_PATH = str(py.magic.autopath().dirpath())+"/rom" + filename = "" if len(sys.argv) > 1: print sys.argv From fijal at codespeak.net Sun May 25 20:05:23 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 25 May 2008 20:05:23 +0200 (CEST) Subject: [pypy-svn] r55213 - in pypy/dist/pypy/rlib: rstruct test Message-ID: <20080525180523.9B21C698059@codespeak.net> Author: fijal Date: Sun May 25 20:05:22 2008 New Revision: 55213 Added: pypy/dist/pypy/rlib/test/test_ieee.py - copied, changed from r55150, pypy/dist/pypy/module/struct/test/test_ieee.py pypy/dist/pypy/rlib/test/test_rstruct.py (contents, props changed) Modified: pypy/dist/pypy/rlib/rstruct/__init__.py Log: Enough hackery to make rpython version of struct.unpack. Looks a bit terrible, but works. Modified: pypy/dist/pypy/rlib/rstruct/__init__.py ============================================================================== --- pypy/dist/pypy/rlib/rstruct/__init__.py (original) +++ pypy/dist/pypy/rlib/rstruct/__init__.py Sun May 25 20:05:22 2008 @@ -1,14 +1,101 @@ +import py from struct import pack, unpack +from pypy.rlib.rstruct.formatiterator import FormatIterator +from pypy.rlib.rstruct.error import StructError +from pypy.rlib.rstruct.nativefmttable import native_is_bigendian from pypy.rpython.extregistry import ExtRegistryEntry -class UnpackEntry(ExtRegistryEntry): - _about_ = unpack +class MasterReader(object): + def __init__(self, s): + self.input = s + self.inputpos = 0 - def compute_result_annotation(self, s_fmt, s_s): - from pypy.annotation import model as annmodel - if not isinstance(s_s, annmodel.SomeString): - raise TypeError("Got %s, string expected" % (s_s,)) - if not s_fmt.is_constant(): - raise ValueError("Can only use struct.unpack with first argument constant in RPython") - + def read(self, count): + end = self.inputpos + count + if end > len(self.input): + raise StructError("unpack str size too short for format") + s = self.input[self.inputpos : end] + self.inputpos = end + return s + +class AbstractReader(object): + pass + +def reader_for_pos(pos): + class ReaderForPos(AbstractReader): + def __init__(self, mr): + self.mr = mr + self.bigendian = native_is_bigendian + + def read(self, count): + return self.mr.read(count) + + def appendobj(self, value): + self.value = value + ReaderForPos.__name__ = 'ReaderForPos%d' % pos + return ReaderForPos + +class FrozenUnpackIterator(FormatIterator): + def __init__(self, fmt): + self.formats = [] + self.fmt = fmt + + def operate(self, fmtdesc, repetitions): + if fmtdesc.needcount: + self.formats.append((fmtdesc, repetitions)) + else: + for i in range(repetitions): + self.formats.append((fmtdesc, 1)) + + def align(self, mask): + pass # XXX + + def _create_unpacking_func(self): + rg = range(len(self.formats)) + perform_lst = [] + miniglobals = {} + miniglobals.update(globals()) + for i in rg: + fmtdesc, rep = self.formats[i] + miniglobals['unpacker%d' % i] = fmtdesc.unpack + if rep == 1: + perform_lst.append('unpacker%d(reader%d)' % (i, i)) + else: + perform_lst.append('unpacker%d(reader%d, %d)' % (i, i, rep)) + miniglobals['reader_cls%d' % i] = reader_for_pos(i) + readers = ";".join(["reader%d = reader_cls%d(master_reader)" % (i, i) + for i in rg]) + perform = ";".join(perform_lst) + unpackers = ','.join(['reader%d.value' % i for i in rg]) + source = py.code.Source(""" + def unpack(s): + master_reader = MasterReader(s) + %(readers)s + %(perform)s + return (%(unpackers)s) + """ % locals()) + exec source.compile() in miniglobals + self.unpack = miniglobals['unpack'] # override not-rpython version + + def unpack(self, s): + # NOT_RPYTHON + return unpack(self.fmt, s) + + def _freeze_(self): + assert self.formats + self._create_unpacking_func() + return True + +def create_unpacker(unpack_str): + fmtiter = FrozenUnpackIterator(unpack_str) + fmtiter.interpret(unpack_str) + return fmtiter +create_unpacker._annspecialcase_ = 'specialize:memo' + +def runpack(fmt, input): + unpacker = create_unpacker(fmt) + return unpacker.unpack(input) +runpack._annspecialcase_ = 'specialize:arg(0)' + + Added: pypy/dist/pypy/rlib/test/test_rstruct.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rlib/test/test_rstruct.py Sun May 25 20:05:22 2008 @@ -0,0 +1,17 @@ + +from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin +from pypy.rlib.rstruct import runpack +import struct + +class BaseTestRStruct(BaseRtypingTest): + def test_unpack(self): + def fn(): + return runpack('ll', '\x03\x00\x00\x00\x05\x00\x00\x00')[0] + assert fn() == 3 + assert self.interpret(fn, []) == 3 + +class TestLLType(BaseTestRStruct, LLRtypeMixin): + pass + +class TestOOType(BaseTestRStruct, OORtypeMixin): + pass From fijal at codespeak.net Sun May 25 21:19:21 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 25 May 2008 21:19:21 +0200 (CEST) Subject: [pypy-svn] r55214 - in pypy/dist/pypy/rlib: rstruct test Message-ID: <20080525191921.54AA8169E1B@codespeak.net> Author: fijal Date: Sun May 25 21:19:18 2008 New Revision: 55214 Modified: pypy/dist/pypy/rlib/rstruct/__init__.py pypy/dist/pypy/rlib/rstruct/nativefmttable.py pypy/dist/pypy/rlib/rstruct/standardfmttable.py pypy/dist/pypy/rlib/test/test_rstruct.py Log: A test and two fixes: * specialize unpackers * fix for alignments Modified: pypy/dist/pypy/rlib/rstruct/__init__.py ============================================================================== --- pypy/dist/pypy/rlib/rstruct/__init__.py (original) +++ pypy/dist/pypy/rlib/rstruct/__init__.py Sun May 25 21:19:18 2008 @@ -19,6 +19,9 @@ self.inputpos = end return s + def align(self, mask): + self.inputpos = (self.inputpos + mask) & ~mask + class AbstractReader(object): pass @@ -43,13 +46,14 @@ def operate(self, fmtdesc, repetitions): if fmtdesc.needcount: - self.formats.append((fmtdesc, repetitions)) + self.formats.append((fmtdesc, repetitions, None)) else: for i in range(repetitions): - self.formats.append((fmtdesc, 1)) + self.formats.append((fmtdesc, 1, None)) def align(self, mask): - pass # XXX + fmt, rep, _ = self.formats.pop() + self.formats.append((fmt, rep, mask)) def _create_unpacking_func(self): rg = range(len(self.formats)) @@ -57,9 +61,11 @@ miniglobals = {} miniglobals.update(globals()) for i in rg: - fmtdesc, rep = self.formats[i] + fmtdesc, rep, mask = self.formats[i] miniglobals['unpacker%d' % i] = fmtdesc.unpack - if rep == 1: + if mask is not None: + perform_lst.append('master_reader.align(%d)' % mask) + if not fmtdesc.needcount: perform_lst.append('unpacker%d(reader%d)' % (i, i)) else: perform_lst.append('unpacker%d(reader%d, %d)' % (i, i, rep)) Modified: pypy/dist/pypy/rlib/rstruct/nativefmttable.py ============================================================================== --- pypy/dist/pypy/rlib/rstruct/nativefmttable.py (original) +++ pypy/dist/pypy/rlib/rstruct/nativefmttable.py Sun May 25 21:19:18 2008 @@ -9,6 +9,7 @@ from pypy.rpython.lltypesystem import lltype, rffi from pypy.rlib.rarithmetic import r_singlefloat from pypy.translator.tool.cbuild import ExternalCompilationInfo +from pypy.rlib.objectmodel import specialize native_is_bigendian = struct.pack("=i", 1) == struct.pack(">i", 1) @@ -31,6 +32,7 @@ for i in range(sizeof_double): fmtiter.result.append(p[i]) + at specialize.argtype(0) def unpack_double(fmtiter): input = fmtiter.read(sizeof_double) p = rffi.cast(rffi.CCHARP, double_buf) @@ -47,6 +49,7 @@ for i in range(sizeof_float): fmtiter.result.append(p[i]) + at specialize.argtype(0) def unpack_float(fmtiter): input = fmtiter.read(sizeof_float) p = rffi.cast(rffi.CCHARP, float_buf) @@ -139,6 +142,7 @@ c = unistr[0] # string->char conversion for the annotator unichar.pack_unichar(c, fmtiter.result) + at specialize.argtype(0) def unpack_unichar(fmtiter): data = fmtiter.read(unichar.UNICODE_SIZE) fmtiter.appendobj(unichar.unpack_unichar(data)) Modified: pypy/dist/pypy/rlib/rstruct/standardfmttable.py ============================================================================== --- pypy/dist/pypy/rlib/rstruct/standardfmttable.py (original) +++ pypy/dist/pypy/rlib/rstruct/standardfmttable.py Sun May 25 21:19:18 2008 @@ -10,6 +10,7 @@ from pypy.rlib.rstruct import ieee from pypy.rlib.unroll import unrolling_iterable from pypy.rlib.rarithmetic import r_uint, r_longlong, r_ulonglong +from pypy.rlib.objectmodel import specialize # In the CPython struct module, pack() unconsistently accepts inputs # that are out-of-range or floats instead of ints. Should we emulate @@ -131,15 +132,19 @@ # ____________________________________________________________ + at specialize.argtype(0) def unpack_pad(fmtiter, count): fmtiter.read(count) + at specialize.argtype(0) def unpack_char(fmtiter): fmtiter.appendobj(fmtiter.read(1)) + at specialize.argtype(0) def unpack_string(fmtiter, count): fmtiter.appendobj(fmtiter.read(count)) + at specialize.argtype(0) def unpack_pascal(fmtiter, count): if count == 0: raise StructError("bad '0p' in struct format") @@ -150,9 +155,10 @@ fmtiter.appendobj(data[1:end]) def make_float_unpacker(size): - return lambda fmtiter: fmtiter.appendobj(ieee.unpack_float( + return specialize.argtype(0)( + lambda fmtiter: fmtiter.appendobj(ieee.unpack_float( fmtiter.read(size), - fmtiter.bigendian)) + fmtiter.bigendian))) # ____________________________________________________________ @@ -175,6 +181,7 @@ inttype = r_ulonglong unroll_range_size = unrolling_iterable(range(size)) + @specialize.argtype(0) def unpack_int(fmtiter): intvalue = inttype(0) s = fmtiter.read(size) Modified: pypy/dist/pypy/rlib/test/test_rstruct.py ============================================================================== --- pypy/dist/pypy/rlib/test/test_rstruct.py (original) +++ pypy/dist/pypy/rlib/test/test_rstruct.py Sun May 25 21:19:18 2008 @@ -6,7 +6,7 @@ class BaseTestRStruct(BaseRtypingTest): def test_unpack(self): def fn(): - return runpack('ll', '\x03\x00\x00\x00\x05\x00\x00\x00')[0] + return runpack('sll', 'a\x00\x00\x00\x03\x00\x00\x00\x04\x00\x00\x00')[1] assert fn() == 3 assert self.interpret(fn, []) == 3 From fijal at codespeak.net Sun May 25 21:19:52 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 25 May 2008 21:19:52 +0200 (CEST) Subject: [pypy-svn] r55215 - pypy/dist/pypy/rlib/rstruct Message-ID: <20080525191952.2BDE1169E1C@codespeak.net> Author: fijal Date: Sun May 25 21:19:51 2008 New Revision: 55215 Modified: pypy/dist/pypy/rlib/rstruct/__init__.py Log: Add a comment Modified: pypy/dist/pypy/rlib/rstruct/__init__.py ============================================================================== --- pypy/dist/pypy/rlib/rstruct/__init__.py (original) +++ pypy/dist/pypy/rlib/rstruct/__init__.py Sun May 25 21:19:51 2008 @@ -1,4 +1,8 @@ +""" WARNING! this module is incomplete and may have rough edges. Use only +if necessary +""" + import py from struct import pack, unpack from pypy.rlib.rstruct.formatiterator import FormatIterator From fijal at codespeak.net Sun May 25 21:41:00 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 25 May 2008 21:41:00 +0200 (CEST) Subject: [pypy-svn] r55216 - in pypy/dist/pypy/rlib: . test Message-ID: <20080525194100.D4F83169F17@codespeak.net> Author: fijal Date: Sun May 25 21:40:58 2008 New Revision: 55216 Added: pypy/dist/pypy/rlib/rzipfile.py (contents, props changed) pypy/dist/pypy/rlib/test/test_rzipfile.py (contents, props changed) Log: Enough support for zipfile on interp level to pass simple test. This will be used by zipimport. Added: pypy/dist/pypy/rlib/rzipfile.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rlib/rzipfile.py Sun May 25 21:40:58 2008 @@ -0,0 +1,242 @@ + +from zipfile import ZIP_STORED, ZIP_DEFLATED +from pypy.rlib.streamio import open_file_as_stream +from pypy.rlib.rstruct import runpack +import os +from pypy.rlib import rzlib +from pypy.rlib.rarithmetic import r_uint, intmask + +# XXX hack to get crc32 to work +from pypy.lib.binascii import crc_32_tab + +rcrc_32_tab = [r_uint(i) for i in crc_32_tab] + +def crc32(s, crc=0): + result = 0 + crc = ~r_uint(crc) & 0xffffffffL + for c in s: + crc = rcrc_32_tab[(crc ^ r_uint(ord(c))) & 0xffL] ^ (crc >> 8) + #/* Note: (crc >> 8) MUST zero fill on left + + result = crc ^ 0xffffffffL + + if result > 2**31: + result = ((result + 2**31) % r_uint(2**32)) - 2**31 + + return result + +# parts copied from zipfile library implementation + +class BadZipfile(Exception): + pass + +# Here are some struct module formats for reading headers +structEndArchive = "<4s4H2lH" # 9 items, end of archive, 22 bytes +stringEndArchive = "PK\005\006" # magic number for end of archive record +structCentralDir = "<4s4B4HlLL5HLl"# 19 items, central directory, 46 bytes +stringCentralDir = "PK\001\002" # magic number for central directory +structFileHeader = "<4s2B4HlLL2H" # 12 items, file header record, 30 bytes +stringFileHeader = "PK\003\004" # magic number for file header + +# indexes of entries in the central directory structure +_CD_SIGNATURE = 0 +_CD_CREATE_VERSION = 1 +_CD_CREATE_SYSTEM = 2 +_CD_EXTRACT_VERSION = 3 +_CD_EXTRACT_SYSTEM = 4 # is this meaningful? +_CD_FLAG_BITS = 5 +_CD_COMPRESS_TYPE = 6 +_CD_TIME = 7 +_CD_DATE = 8 +_CD_CRC = 9 +_CD_COMPRESSED_SIZE = 10 +_CD_UNCOMPRESSED_SIZE = 11 +_CD_FILENAME_LENGTH = 12 +_CD_EXTRA_FIELD_LENGTH = 13 +_CD_COMMENT_LENGTH = 14 +_CD_DISK_NUMBER_START = 15 +_CD_INTERNAL_FILE_ATTRIBUTES = 16 +_CD_EXTERNAL_FILE_ATTRIBUTES = 17 +_CD_LOCAL_HEADER_OFFSET = 18 + +# indexes of entries in the local file header structure +_FH_SIGNATURE = 0 +_FH_EXTRACT_VERSION = 1 +_FH_EXTRACT_SYSTEM = 2 # is this meaningful? +_FH_GENERAL_PURPOSE_FLAG_BITS = 3 +_FH_COMPRESSION_METHOD = 4 +_FH_LAST_MOD_TIME = 5 +_FH_LAST_MOD_DATE = 6 +_FH_CRC = 7 +_FH_COMPRESSED_SIZE = 8 +_FH_UNCOMPRESSED_SIZE = 9 +_FH_FILENAME_LENGTH = 10 +_FH_EXTRA_FIELD_LENGTH = 11 + +class EndRecStruct(object): + def __init__(self, stuff, comment, filesize): + self.stuff = stuff + self.comment = comment + self.filesize = filesize + +def _EndRecData(fpin): + """Return data from the "End of Central Directory" record, or None. + + The data is a list of the nine items in the ZIP "End of central dir" + record followed by a tenth item, the file seek offset of this record.""" + fpin.seek(-22, 2) # Assume no archive comment. + filesize = fpin.tell() + 22 # Get file size + data = fpin.readall() + start = len(data)-2 + assert start > 0 + if data[0:4] == stringEndArchive and data[start:] == "\000\000": + endrec = runpack(structEndArchive, data) + return EndRecStruct(endrec, "", filesize - 22) + # Search the last END_BLOCK bytes of the file for the record signature. + # The comment is appended to the ZIP file and has a 16 bit length. + # So the comment may be up to 64K long. We limit the search for the + # signature to a few Kbytes at the end of the file for efficiency. + # also, the signature must not appear in the comment. + END_BLOCK = min(filesize, 1024 * 4) + fpin.seek(filesize - END_BLOCK, 0) + data = fpin.readall() + start = data.rfind(stringEndArchive) + if start >= 0: # Correct signature string was found + endrec = runpack(structEndArchive, data[start:start+22]) + comment = data[start+22:] + if endrec[7] == len(comment): # Comment length checks out + # Append the archive comment and start offset + return EndRecStruct(endrec, comment, filesize - END_BLOCK + start) + return # Error, return None + +class RZipInfo(object): + def __init__(self, filename, date_time=(1980,1,1,0,0,0)): + self.orig_filename = filename + null_byte = filename.find(chr(0)) + if null_byte >= 0: + filename = filename[0:null_byte] +# This is used to ensure paths in generated ZIP files always use +# forward slashes as the directory separator, as required by the +# ZIP format specification. + if os.sep != "/": + filename = filename.replace(os.sep, "/") + self.filename = filename # Normalized file name + self.date_time = date_time # year, month, day, hour, min, sec + # Standard values: + self.compress_type = ZIP_STORED # Type of compression for the file + self.comment = "" # Comment for each file + self.extra = "" # ZIP extra data + self.create_system = 0 # System which created ZIP archive + self.create_version = 20 # Version which created ZIP archive + self.extract_version = 20 # Version needed to extract archive + self.reserved = 0 # Must be zero + self.flag_bits = 0 # ZIP flag bits + self.volume = 0 # Volume number of file header + self.internal_attr = 0 # Internal attributes + self.external_attr = 0 # External file attributes + # Other attributes are set by class ZipFile: + # header_offset Byte offset to the file header + # file_offset Byte offset to the start of the file data + # CRC CRC-32 of the uncompressed file + # compress_size Size of the compressed file + # file_size Size of the uncompressed file + +class RZipFile(object): + def __init__(self, zipname, mode='r', compression=ZIP_STORED): + if mode != 'r': + raise TypeError("Read only support by now") + self.compression = compression + self.mode = mode + self.filelist = [] + self.NameToInfo = {} + fp = open_file_as_stream(zipname, mode, 1024) + self._GetContents(fp) + self.fp = fp + + def _GetContents(self, fp): + endrec = _EndRecData(fp) + if not endrec: + raise BadZipfile, "File is not a zip file" + size_cd = endrec.stuff[5] # bytes in central directory + offset_cd = endrec.stuff[6] # offset of central directory + self.comment = endrec.comment + x = endrec.filesize - size_cd + concat = x - offset_cd + self.start_dir = offset_cd + concat + fp.seek(self.start_dir, 0) + total = 0 + while total < size_cd: + centdir = fp.read(46) + total = total + 46 + if centdir[0:4] != stringCentralDir: + raise BadZipfile, "Bad magic number for central directory" + centdir = runpack(structCentralDir, centdir) + filename = fp.read(centdir[_CD_FILENAME_LENGTH]) + # Create ZipInfo instance to store file information + x = RZipInfo(filename) + x.extra = fp.read(centdir[_CD_EXTRA_FIELD_LENGTH]) + x.comment = fp.read(centdir[_CD_COMMENT_LENGTH]) + total = (total + centdir[_CD_FILENAME_LENGTH] + + centdir[_CD_EXTRA_FIELD_LENGTH] + + centdir[_CD_COMMENT_LENGTH]) + x.header_offset = centdir[_CD_LOCAL_HEADER_OFFSET] + concat + # file_offset must be computed below... + (x.create_version, x.create_system, x.extract_version, x.reserved, + x.flag_bits, x.compress_type, t, d, + x.CRC, x.compress_size, x.file_size) = centdir[1:12] + x.volume, x.internal_attr, x.external_attr = centdir[15:18] + # Convert date/time code to (year, month, day, hour, min, sec) + x.date_time = ( (d>>9)+1980, (d>>5)&0xF, d&0x1F, + t>>11, (t>>5)&0x3F, (t&0x1F) * 2 ) + self.filelist.append(x) + self.NameToInfo[x.filename] = x + for data in self.filelist: + fp.seek(data.header_offset, 0) + fheader = fp.read(30) + if fheader[0:4] != stringFileHeader: + raise BadZipfile, "Bad magic number for file header" + fheader = runpack(structFileHeader, fheader) + # file_offset is computed here, since the extra field for + # the central directory and for the local file header + # refer to different fields, and they can have different + # lengths + data.file_offset = (data.header_offset + 30 + + fheader[_FH_FILENAME_LENGTH] + + fheader[_FH_EXTRA_FIELD_LENGTH]) + fname = fp.read(fheader[_FH_FILENAME_LENGTH]) + if fname != data.orig_filename: + raise RuntimeError, \ + 'File name in directory "%s" and header "%s" differ.' % ( + data.orig_filename, fname) + fp.seek(self.start_dir, 0) + + def getinfo(self, filename): + """Return the instance of ZipInfo given 'filename'.""" + return self.NameToInfo[filename] + + def read(self, filename): + zinfo = self.getinfo(filename) + filepos = self.fp.tell() + self.fp.seek(zinfo.file_offset, 0) + bytes = self.fp.read(intmask(zinfo.compress_size)) + self.fp.seek(filepos, 0) + if zinfo.compress_type == ZIP_STORED: + pass + elif zinfo.compress_type == ZIP_DEFLATED: + raise NotImplementedError + # zlib compress/decompress code by Jeremy Hylton of CNRI + dc = zlib.decompressobj(-15) + bytes = dc.decompress(bytes) + # need to feed in unused pad byte so that zlib won't choke + ex = dc.decompress('Z') + dc.flush() + if ex: + bytes = bytes + ex + else: + raise BadZipfile, \ + "Unsupported compression method %d for file %s" % \ + (zinfo.compress_type, filename) + crc = crc32(bytes) + if crc != r_uint(zinfo.CRC): + raise BadZipfile, "Bad CRC-32 for file %s" % filename + return bytes + Added: pypy/dist/pypy/rlib/test/test_rzipfile.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rlib/test/test_rzipfile.py Sun May 25 21:40:58 2008 @@ -0,0 +1,35 @@ + +from pypy.rlib.rzipfile import RZipFile +from pypy.tool.udir import udir +from zipfile import ZIP_STORED, ZIP_DEFLATED, ZipInfo, ZipFile +from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin +import os +import time + +class BaseTestRZipFile(BaseRtypingTest): + + def setup_class(cls): + tmpdir = udir.ensure('zipimport_%s' % cls.__name__, dir=1) + zipname = str(tmpdir.join("somezip.zip")) + cls.zipname = zipname + zipfile = ZipFile(zipname, "w") + cls.year = time.localtime(time.time())[0] + zipfile.writestr("one", "stuff") + zipfile.writestr("dir" + os.path.sep + "two", "otherstuff") + zipfile.close() + + def test_rzipfile(self): + zipname = self.zipname + year = self.year + compression = self.compression + def one(): + rzip = RZipFile(zipname, "r", compression) + info = rzip.getinfo('one') + return (info.date_time[0] == year and + rzip.read('one') == 'stuff') + + assert one() + assert self.interpret(one, []) + +class TestRZipFile(BaseTestRZipFile, LLRtypeMixin): + compression = ZIP_STORED From santagada at codespeak.net Sun May 25 22:02:24 2008 From: santagada at codespeak.net (santagada at codespeak.net) Date: Sun, 25 May 2008 22:02:24 +0200 (CEST) Subject: [pypy-svn] r55217 - pypy/branch/js-refactoring/pypy/lang/js Message-ID: <20080525200224.58705698049@codespeak.net> Author: santagada Date: Sun May 25 22:02:22 2008 New Revision: 55217 Modified: pypy/branch/js-refactoring/pypy/lang/js/interpreter.py pypy/branch/js-refactoring/pypy/lang/js/jsobj.py Log: better treatament of NAN and INFINITY and removal of some dead code Modified: pypy/branch/js-refactoring/pypy/lang/js/interpreter.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/interpreter.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/interpreter.py Sun May 25 22:02:22 2008 @@ -4,13 +4,13 @@ from pypy.lang.js.astbuilder import ASTBuilder from pypy.lang.js.jsobj import global_context, W_Object,\ w_Undefined, W_NewBuiltin, W_IntNumber, w_Null, create_object, W_Boolean,\ - W_FloatNumber, NaN, Infinity, W_String, W_Builtin, W_Array, w_Null,\ + W_FloatNumber, W_String, W_Builtin, W_Array, w_Null,\ isnull_or_undefined, W_PrimitiveObject, W_ListObject from pypy.lang.js.execution import ThrowException, JsTypeError from pypy.rlib.objectmodel import we_are_translated from pypy.rlib.streamio import open_file_as_stream from pypy.lang.js.jscode import JsCode -from pypy.rlib.rarithmetic import NAN, INFINITY, isnan +from pypy.rlib.rarithmetic import NAN, INFINITY, isnan, isinf ASTBUILDER = ASTBuilder() @@ -124,7 +124,7 @@ def parseIntjs(ctx, args, this): if len(args) < 1: - return W_FloatNumber(NaN) + return W_FloatNumber(NAN) s = args[0].ToString(ctx).strip(" ") if len(args) > 1: radix = args[1].ToInt32() @@ -134,21 +134,21 @@ radix = 16 s = s[2:] if s == '' or radix < 2 or radix > 36: - return W_FloatNumber(NaN) + return W_FloatNumber(NAN) try: n = int(s, radix) except ValueError: - return W_FloatNumber(NaN) + return W_FloatNumber(NAN) return W_IntNumber(n) def parseFloatjs(ctx, args, this): if len(args) < 1: - return W_FloatNumber(NaN) + return W_FloatNumber(NAN) s = args[0].ToString(ctx).strip(" ") try: n = float(s) except ValueError: - n = NaN + n = NAN return W_FloatNumber(n) @@ -165,32 +165,10 @@ if len(args) < 1: return W_Boolean(True) n = args[0].ToNumber(ctx) - if n == Infinity or n == -Infinity or n == NaN: + if isinf(n) or isnan(n): return W_Boolean(False) else: return W_Boolean(True) - -def booleanjs(ctx, args, this): - if len(args) > 0: - return W_Boolean(args[0].ToBoolean()) - return W_Boolean(False) - -def stringjs(ctx, args, this): - if len(args) > 0: - return W_String(args[0].ToString(ctx)) - return W_String('') - -def arrayjs(ctx, args, this): - arr = W_Array() - for i in range(len(args)): - arr.Put(str(i), args[i]) - return arr - - -def numberjs(ctx, args, this): - if len(args) > 0: - return W_FloatNumber(args[0].ToNumber(ctx)) - return W_IntNumber(0) def absjs(ctx, args, this): val = args[0] @@ -502,11 +480,11 @@ w_Number.Put('MAX_VALUE', W_FloatNumber(1.7976931348623157e308), ro=True, dd=True) w_Number.Put('MIN_VALUE', W_FloatNumber(0), ro=True, dd=True) - w_Number.Put('NaN', W_FloatNumber(NaN), ro=True, dd=True) + w_Number.Put('NaN', W_FloatNumber(NAN), ro=True, dd=True) # ^^^ this is exactly in test case suite - w_Number.Put('POSITIVE_INFINITY', W_FloatNumber(Infinity), + w_Number.Put('POSITIVE_INFINITY', W_FloatNumber(INFINITY), ro=True, dd=True) - w_Number.Put('NEGATIVE_INFINITY', W_FloatNumber(-Infinity), + w_Number.Put('NEGATIVE_INFINITY', W_FloatNumber(-INFINITY), ro=True, dd=True) @@ -566,14 +544,14 @@ w_Date = W_DateFake(ctx, Class='Date') w_Global.Put('Date', w_Date) - w_Global.Put('NaN', W_FloatNumber(NaN)) - w_Global.Put('Infinity', W_FloatNumber(Infinity)) + w_Global.Put('NaN', W_FloatNumber(NAN)) + w_Global.Put('Infinity', W_FloatNumber(INFINITY)) w_Global.Put('undefined', w_Undefined) w_Global.Put('eval', W_Builtin(evaljs)) w_Global.Put('parseInt', W_Builtin(parseIntjs)) w_Global.Put('parseFloat', W_Builtin(parseFloatjs)) w_Global.Put('isNaN', W_Builtin(isnanjs)) - w_Global.Put('isFinite', W_Builtin(isnanjs)) + w_Global.Put('isFinite', W_Builtin(isfinitejs)) w_Global.Put('print', W_Builtin(printjs)) w_Global.Put('this', w_Global) Modified: pypy/branch/js-refactoring/pypy/lang/js/jsobj.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/jsobj.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/jsobj.py Sun May 25 22:02:22 2008 @@ -1,15 +1,12 @@ # encoding: utf-8 from pypy.rlib.rarithmetic import r_uint, intmask, isnan, isinf,\ - ovfcheck_float_to_int + ovfcheck_float_to_int, NAN from pypy.lang.js.execution import ThrowException, JsTypeError,\ RangeError, ReturnException class SeePage(NotImplementedError): pass -Infinity = 1e300 * 1e300 -NaN = Infinity/Infinity - class Property(object): def __init__(self, name, value, dd=False, ro=False, de=False, it=False): @@ -81,7 +78,7 @@ return "w_undefined" def ToNumber(self, ctx): - return NaN + return NAN def ToBoolean(self): return False @@ -410,7 +407,7 @@ try: return float(self.strval) except ValueError: - return NaN + return NAN class W_BaseNumber(W_Primitive): """ Base class for numbers, both known to be floats From fijal at codespeak.net Sun May 25 22:31:45 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 25 May 2008 22:31:45 +0200 (CEST) Subject: [pypy-svn] r55218 - pypy/dist/pypy/interpreter Message-ID: <20080525203145.D033A698049@codespeak.net> Author: fijal Date: Sun May 25 22:31:42 2008 New Revision: 55218 Modified: pypy/dist/pypy/interpreter/gateway.py Log: These functions should not catch RuntimeError as well Modified: pypy/dist/pypy/interpreter/gateway.py ============================================================================== --- pypy/dist/pypy/interpreter/gateway.py (original) +++ pypy/dist/pypy/interpreter/gateway.py Sun May 25 22:31:42 2008 @@ -486,7 +486,9 @@ raise OperationError(space.w_KeyboardInterrupt, space.w_None) except MemoryError: - raise OperationError(space.w_MemoryError, space.w_None) + raise OperationError(space.w_MemoryError, space.w_None) + except NotImplementedError, e: + raise except RuntimeError, e: raise OperationError(space.w_RuntimeError, space.wrap("internal error: " + str(e))) @@ -510,7 +512,9 @@ except KeyboardInterrupt: raise OperationError(space.w_KeyboardInterrupt, space.w_None) except MemoryError: - raise OperationError(space.w_MemoryError, space.w_None) + raise OperationError(space.w_MemoryError, space.w_None) + except NotImplementedError, e: + raise except RuntimeError, e: raise OperationError(space.w_RuntimeError, space.wrap("internal error: " + str(e))) @@ -537,7 +541,9 @@ except KeyboardInterrupt: raise OperationError(space.w_KeyboardInterrupt, space.w_None) except MemoryError: - raise OperationError(space.w_MemoryError, space.w_None) + raise OperationError(space.w_MemoryError, space.w_None) + except NotImplementedError, e: + raise except RuntimeError, e: raise OperationError(space.w_RuntimeError, space.wrap("internal error: " + str(e))) @@ -574,7 +580,9 @@ except KeyboardInterrupt: raise OperationError(space.w_KeyboardInterrupt, space.w_None) except MemoryError: - raise OperationError(space.w_MemoryError, space.w_None) + raise OperationError(space.w_MemoryError, space.w_None) + except NotImplementedError, e: + raise except RuntimeError, e: raise OperationError(space.w_RuntimeError, space.wrap("internal error: " + str(e))) @@ -595,7 +603,9 @@ except KeyboardInterrupt: raise OperationError(space.w_KeyboardInterrupt, space.w_None) except MemoryError: - raise OperationError(space.w_MemoryError, space.w_None) + raise OperationError(space.w_MemoryError, space.w_None) + except NotImplementedError, e: + raise except RuntimeError, e: raise OperationError(space.w_RuntimeError, space.wrap("internal error: " + str(e))) @@ -616,7 +626,9 @@ except KeyboardInterrupt: raise OperationError(space.w_KeyboardInterrupt, space.w_None) except MemoryError: - raise OperationError(space.w_MemoryError, space.w_None) + raise OperationError(space.w_MemoryError, space.w_None) + except NotImplementedError, e: + raise except RuntimeError, e: raise OperationError(space.w_RuntimeError, space.wrap("internal error: " + str(e))) @@ -637,7 +649,9 @@ except KeyboardInterrupt: raise OperationError(space.w_KeyboardInterrupt, space.w_None) except MemoryError: - raise OperationError(space.w_MemoryError, space.w_None) + raise OperationError(space.w_MemoryError, space.w_None) + except NotImplementedError, e: + raise except RuntimeError, e: raise OperationError(space.w_RuntimeError, space.wrap("internal error: " + str(e))) From fijal at codespeak.net Sun May 25 23:14:14 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 25 May 2008 23:14:14 +0200 (CEST) Subject: [pypy-svn] r55219 - in pypy/dist/pypy/rlib: . test Message-ID: <20080525211414.BC9A0169E22@codespeak.net> Author: fijal Date: Sun May 25 23:14:13 2008 New Revision: 55219 Modified: pypy/dist/pypy/rlib/rzipfile.py pypy/dist/pypy/rlib/test/test_rzipfile.py Log: A test and a fix for compression Modified: pypy/dist/pypy/rlib/rzipfile.py ============================================================================== --- pypy/dist/pypy/rlib/rzipfile.py (original) +++ pypy/dist/pypy/rlib/rzipfile.py Sun May 25 23:14:13 2008 @@ -20,9 +20,6 @@ result = crc ^ 0xffffffffL - if result > 2**31: - result = ((result + 2**31) % r_uint(2**32)) - 2**31 - return result # parts copied from zipfile library implementation @@ -146,6 +143,7 @@ if mode != 'r': raise TypeError("Read only support by now") self.compression = compression + self.filename = zipname self.mode = mode self.filelist = [] self.NameToInfo = {} @@ -223,14 +221,15 @@ if zinfo.compress_type == ZIP_STORED: pass elif zinfo.compress_type == ZIP_DEFLATED: - raise NotImplementedError - # zlib compress/decompress code by Jeremy Hylton of CNRI - dc = zlib.decompressobj(-15) - bytes = dc.decompress(bytes) - # need to feed in unused pad byte so that zlib won't choke - ex = dc.decompress('Z') + dc.flush() - if ex: - bytes = bytes + ex + stream = rzlib.inflateInit(wbits=-15) + try: + bytes, _, _ = rzlib.decompress(stream, bytes) + # need to feed in unused pad byte so that zlib won't choke + ex, _, _ = rzlib.decompress(stream, 'Z') + if ex: + bytes = bytes + ex + finally: + rzlib.inflateEnd(stream) else: raise BadZipfile, \ "Unsupported compression method %d for file %s" % \ Modified: pypy/dist/pypy/rlib/test/test_rzipfile.py ============================================================================== --- pypy/dist/pypy/rlib/test/test_rzipfile.py (original) +++ pypy/dist/pypy/rlib/test/test_rzipfile.py Sun May 25 23:14:13 2008 @@ -12,7 +12,7 @@ tmpdir = udir.ensure('zipimport_%s' % cls.__name__, dir=1) zipname = str(tmpdir.join("somezip.zip")) cls.zipname = zipname - zipfile = ZipFile(zipname, "w") + zipfile = ZipFile(zipname, "w", compression=cls.compression) cls.year = time.localtime(time.time())[0] zipfile.writestr("one", "stuff") zipfile.writestr("dir" + os.path.sep + "two", "otherstuff") @@ -33,3 +33,6 @@ class TestRZipFile(BaseTestRZipFile, LLRtypeMixin): compression = ZIP_STORED + +class TestRZipFileCompressed(BaseTestRZipFile, LLRtypeMixin): + compression = ZIP_DEFLATED From fijal at codespeak.net Sun May 25 23:30:08 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 25 May 2008 23:30:08 +0200 (CEST) Subject: [pypy-svn] r55220 - pypy/dist/pypy/module/zipimport Message-ID: <20080525213008.4F2DD169E83@codespeak.net> Author: fijal Date: Sun May 25 23:30:05 2008 New Revision: 55220 Modified: pypy/dist/pypy/module/zipimport/app_zipimport.py Log: Be a bit more compatible Modified: pypy/dist/pypy/module/zipimport/app_zipimport.py ============================================================================== --- pypy/dist/pypy/module/zipimport/app_zipimport.py (original) +++ pypy/dist/pypy/module/zipimport/app_zipimport.py Sun May 25 23:30:05 2008 @@ -1,5 +1,5 @@ -class ZipImportError(Exception): +class ZipImportError(ImportError): pass _zip_directory_cache = {} From fijal at codespeak.net Sun May 25 23:33:37 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 25 May 2008 23:33:37 +0200 (CEST) Subject: [pypy-svn] r55221 - pypy/dist/pypy/module/zipimport Message-ID: <20080525213337.080F9169E83@codespeak.net> Author: fijal Date: Sun May 25 23:33:36 2008 New Revision: 55221 Modified: pypy/dist/pypy/module/zipimport/interp_zipimport.py Log: Move to rzipfile interface, simplifies few things + makes sure that we can import stdlib from zipfile Modified: pypy/dist/pypy/module/zipimport/interp_zipimport.py ============================================================================== --- pypy/dist/pypy/module/zipimport/interp_zipimport.py (original) +++ pypy/dist/pypy/module/zipimport/interp_zipimport.py Sun May 25 23:33:36 2008 @@ -9,6 +9,7 @@ from pypy.interpreter.module import Module from pypy.module.__builtin__ import importing from pypy.rlib.unroll import unrolling_iterable +from pypy.rlib.rzipfile import RZipFile, BadZipfile import os import stat @@ -25,10 +26,10 @@ (False, False, '.py')]) class W_ZipImporter(Wrappable): - def __init__(self, space, name, w_dir, prefix): + def __init__(self, space, name, dir, prefix): self.space = space self.name = name - self.w_dir = w_dir + self.dir = dir self.prefix = prefix def getprefix(space, self): @@ -48,10 +49,9 @@ def check_newer_pyfile(self, space, filename, timestamp): w = space.wrap try: - w_info = space.call_function(space.getattr(self.w_dir, - w('getinfo')), w(filename)) - w_all = space.getattr(w_info, w('date_time')) - except OperationError, e: + info = self.dir.getinfo(filename) + t = info.date_time + except (BadZipfile, KeyError): # in either case, this is a fallback return False else: @@ -59,8 +59,9 @@ w('mktime')) # XXX this is incredible fishing around module limitations # in order to compare timestamps of .py and .pyc files - all = space.unpackiterable(w_all) - all += [w(0), w(1), w(-1)] + # we need time.mktime support on rpython level + all = [w(t[0]), w(t[1]), w(t[2]), w(t[3]), w(t[4]), + w(t[5]), w(0), w(1), w(-1)] mtime = int(space.float_w(space.call_function(w_mktime, space.newtuple(all)))) return mtime > timestamp @@ -87,12 +88,10 @@ filename = filename.replace(os.path.sep, ZIPSEP) w = space.wrap try: - return space.call(space.getattr(self.w_dir, w('getinfo')), - space.newlist([w(filename)])) - except OperationError, e: - if not e.match(space, space.w_KeyError): - # should never happen - raise e + self.dir.getinfo(filename) + return True + except KeyError: + return False def find_module(self, space, fullname, w_path=None): filename = self.mangle(fullname) @@ -144,10 +143,9 @@ filename = filename.replace(os.path.sep, ZIPSEP) w = space.wrap try: - return space.call_function(space.getattr(self.w_dir, w('read')), - w(filename)) - except OperationError, e: - raise OperationError(space.w_IOError, e.w_value) + return w(self.dir.read(filename)) + except (KeyError, OSError): + raise OperationError(space.w_IOError, space.wrap("Error reading file")) get_data.unwrap_spec = ['self', ObjSpace, str] def get_code(self, space, fullname): @@ -188,8 +186,7 @@ def getarchive(space, self): space = self.space - return space.getattr(self.w_dir, space.wrap('filename')) - + return space.wrap(self.dir.filename) def descr_new_zipimporter(space, w_type, name): w_zip_cache = space.getattr(space.getbuiltinmodule('zipimport'), @@ -204,7 +201,9 @@ except OperationError, o: if not o.match(space, space.w_KeyError): raise + # XXX think about what to do here space.setitem(w_zip_cache, space.wrap(name), space.w_None) + print name ok = False parts = name.split(os.path.sep) filename = "" # make annotator happy @@ -227,19 +226,12 @@ stop = len(filename)-len(last_elem) assert stop > 0 prefix = filename[:stop] - w_import = space.builtin.get('__import__') - w_zipfile = space.call(w_import, space.newlist([ - space.wrap('zipfile'), - space.newdict(), - space.newdict(), - space.newlist([])])) - w_ZipFile = space.getattr(w_zipfile, space.wrap('ZipFile')) try: - w_dir = space.call(w_ZipFile, space.newlist([space.wrap(filename)])) - except OperationError, e: # we catch everything as this function + dir = RZipFile(filename, 'r') + except (BadZipfile, OSError): raise OperationError(space.w_ImportError, space.wrap( "%s seems not to be a zipfile" % (filename,))) - w_result = space.wrap(W_ZipImporter(space, name, w_dir, prefix)) + w_result = space.wrap(W_ZipImporter(space, name, dir, prefix)) space.setitem(w_zip_cache, space.wrap(name), w_result) return w_result @@ -257,3 +249,4 @@ archive = GetSetProperty(W_ZipImporter.getarchive), prefix = GetSetProperty(W_ZipImporter.getprefix), ) + From fijal at codespeak.net Sun May 25 23:34:38 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 25 May 2008 23:34:38 +0200 (CEST) Subject: [pypy-svn] r55222 - pypy/dist/pypy/module/zipimport Message-ID: <20080525213438.CE1AB169E83@codespeak.net> Author: fijal Date: Sun May 25 23:34:37 2008 New Revision: 55222 Modified: pypy/dist/pypy/module/zipimport/interp_zipimport.py Log: oops, kill debug print Modified: pypy/dist/pypy/module/zipimport/interp_zipimport.py ============================================================================== --- pypy/dist/pypy/module/zipimport/interp_zipimport.py (original) +++ pypy/dist/pypy/module/zipimport/interp_zipimport.py Sun May 25 23:34:37 2008 @@ -203,7 +203,6 @@ raise # XXX think about what to do here space.setitem(w_zip_cache, space.wrap(name), space.w_None) - print name ok = False parts = name.split(os.path.sep) filename = "" # make annotator happy From cami at codespeak.net Mon May 26 00:42:53 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Mon, 26 May 2008 00:42:53 +0200 (CEST) Subject: [pypy-svn] r55224 - in pypy/dist/pypy/lang/gameboy: . test Message-ID: <20080525224253.3A37C168530@codespeak.net> Author: cami Date: Mon May 26 00:42:50 2008 New Revision: 55224 Modified: pypy/dist/pypy/lang/gameboy/constants.py pypy/dist/pypy/lang/gameboy/cpu.py pypy/dist/pypy/lang/gameboy/gameboyTest.py pypy/dist/pypy/lang/gameboy/test/test_cpu.py pypy/dist/pypy/lang/gameboy/test/test_gameboy.py pypy/dist/pypy/lang/gameboy/video.py Log: hacky version which produces visual oudput for the testrom and for kirbys dreamland. Modified: pypy/dist/pypy/lang/gameboy/constants.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/constants.py (original) +++ pypy/dist/pypy/lang/gameboy/constants.py Mon May 26 00:42:50 2008 @@ -71,6 +71,7 @@ C_FLAG = 0x10 RESET_A = 0x01 +#RESET_F = 0xB0 RESET_F = 0x80 RESET_BC = 0x0013 RESET_DE = 0x00D8 Modified: pypy/dist/pypy/lang/gameboy/cpu.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/cpu.py (original) +++ pypy/dist/pypy/lang/gameboy/cpu.py Mon May 26 00:42:50 2008 @@ -131,17 +131,11 @@ class FlagRegister(Register): - def __init__(self, cpu): + def __init__(self, cpu, reset_value): assert isinstance(cpu, CPU) self.cpu = cpu + self.reset_value = reset_value self.reset() - #added for rpython type inference - self.z_flag = False - self.n_flag = False - self.h_flag = False - self.c_flag = False - self.p_flag = False - self.s_flag = False def reset(self): self.partial_reset() @@ -241,7 +235,7 @@ self.sp = DoubleRegister(self, Register(self), Register(self), reset_value=constants.RESET_SP) self.a = Register(self, constants.RESET_A) - self.f = FlagRegister(self) + self.f = FlagRegister(self, constants.RESET_F) self.af = DoubleRegister(self, self.a, self.f) @@ -834,7 +828,7 @@ def get_fetchadded_sp(self): # 1 cycle - offset = self.fetch() # 1 cycle + offset = self.process_2_complement(self.fetch()) # 1 cycle s = (self.sp.get() + offset) & 0xFFFF self.f.reset() if (offset >= 0): @@ -848,7 +842,14 @@ if (s & 0x0F00) > (self.sp.get() & 0x0F00): self.f.h_flag = True return s - + + def process_2_complement(self, value): + # check if the left most bit is set + if (value >> 7) == 1: + return -((~value) & 0xFF)-1 + else : + return value + def complement_carry_flag(self): # CCF/SCF self.f.partial_reset(keep_z=True, keep_c=True) @@ -877,7 +878,7 @@ def relative_unconditional_jump(self): # JR +nn, 3 cycles #pc = pc & 0xFF00 + ((pc & 0x00FF) + add) & 0xFF - self.pc.add(self.fetch()) # 3 + 1 cycles + self.pc.add(self.process_2_complement(self.fetch())) # 3 + 1 cycles self.cycles += 1 def relative_conditional_jump(self, cc): Modified: pypy/dist/pypy/lang/gameboy/gameboyTest.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/gameboyTest.py (original) +++ pypy/dist/pypy/lang/gameboy/gameboyTest.py Mon May 26 00:42:50 2008 @@ -11,15 +11,14 @@ print sys.argv filename = sys.argv[1] else: - pos = str(8) + pos = str(9) filename = ROM_PATH+"/rom"+pos+"/rom"+pos+".gb" print "loading rom: ", str(filename) gameBoy = GameBoyImplementation() try: gameBoy.load_cartridge_file(str(filename)) except: + gameBoy.load_cartridge_file(str(filename), verify=False) print "Cartridge is Corrupted!" - -gameBoy.load_cartridge_file(str(filename), verify=False) gameBoy.mainLoop() #pdb.runcall(gameBoy.mainLoop) Modified: pypy/dist/pypy/lang/gameboy/test/test_cpu.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/test/test_cpu.py (original) +++ pypy/dist/pypy/lang/gameboy/test/test_cpu.py Mon May 26 00:42:50 2008 @@ -31,6 +31,15 @@ # ------------------------------------------------------------------------------ # TEST CPU +def test_reset(): + cpu = get_cpu() + assert cpu.a.get() == 0x01 + #assert cpu.f.get() == 0xB0 + assert cpu.b.get() == 0x00 + assert cpu.c.get() == 0x13 + assert cpu.de.get() == 0x00D8 + assert cpu.hl.get() == 0x014D + #assert cpu.sp.get() == 0xFFE def test_getters(): cpu = get_cpu() Modified: pypy/dist/pypy/lang/gameboy/test/test_gameboy.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/test/test_gameboy.py (original) +++ pypy/dist/pypy/lang/gameboy/test/test_gameboy.py Mon May 26 00:42:50 2008 @@ -11,4 +11,35 @@ def test_init(): - gameboy = get_gameboy() \ No newline at end of file + gameboy = get_gameboy() + gameboy.read(0xFF05) == 0x00 # TIMA + gameboy.read(0xFF06) == 0x00 # TMA + gameboy.read(0xFF07) == 0x00 # TAC + gameboy.read(0xFF10) == 0x80 # NR10 a.k.a. rAUD1SWEEP + gameboy.read(0xFF11) == 0xBF # NR11 a.k.a. rAUD1LEN + gameboy.read(0xFF12) == 0xF3 # NR12 a.k.a. rAUD1ENV + gameboy.read(0xFF14) == 0xBF # NR14 a.k.a. rAUD1HIGH + gameboy.read(0xFF16) == 0x3F # NR21 a.k.a. rAUD2LEN + gameboy.read(0xFF17) == 0x00 # NR22 a.k.a. rAUD2ENV + gameboy.read(0xFF19) == 0xBF # NR24 a.k.a. rAUD2HIGH + gameboy.read(0xFF1A) == 0x7F # NR30 a.k.a. rAUD3ENA + gameboy.read(0xFF1B) == 0xFF # NR31 a.k.a. rAUD3LEN + gameboy.read(0xFF1C) == 0x9F # NR32 a.k.a. rAUD3LEVEL + gameboy.read(0xFF1E) == 0xBF # NR33 a.k.a. rAUD3LOW + gameboy.read(0xFF20) == 0xFF # NR41 a.k.a. rAUD4LEN + gameboy.read(0xFF21) == 0x00 # NR42 a.k.a. rAUD4ENV + gameboy.read(0xFF22) == 0x00 # NR43 a.k.a. rAUD4POLY + gameboy.read(0xFF23) == 0xBF # NR44 a.k.a. rAUD4GO + gameboy.read(0xFF24) == 0x77 # NR50 a.k.a. rAUDVOL + gameboy.read(0xFF25) == 0xF3 # NR51 a.k.a. rAUDTERM + gameboy.read(0xFF26) == 0xF1 # NR52 + gameboy.read(0xFF40) == 0x91 # LCDC + gameboy.read(0xFF42) == 0x00 # SCY + gameboy.read(0xFF43) == 0x00 # SCX + gameboy.read(0xFF45) == 0x00 # LYC + gameboy.read(0xFF47) == 0xFC # BGP + gameboy.read(0xFF48) == 0xFF # OBP0 + gameboy.read(0xFF49) == 0xFF # OBP1 + gameboy.read(0xFF4A) == 0x00 # WY + gameboy.read(0xFF4B) == 0x00 # WX + gameboy.read(0xFFFF) == 0x00 # IE \ No newline at end of file Modified: pypy/dist/pypy/lang/gameboy/video.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/video.py (original) +++ pypy/dist/pypy/lang/gameboy/video.py Mon May 26 00:42:50 2008 @@ -8,6 +8,7 @@ +# ----------------------------------------------------------------------------- class VideoCallWraper(object): def call(self, pos, color, mask): pass @@ -29,6 +30,40 @@ self.video.set_tile_line(pos, color, mask) +# ----------------------------------------------------------------------------- + +def VideoStatus(object): + def __init__(self, video): + self.video = video + self.reset() + + def reset(self): + self.mode = False + self.lyc_ly_coincidence = False + self.h_blank_interrupt = False + self.oam_interrupt = False + self.h_blank_interrupt = False + self.v_blank_interrupt = False + #Coincidence Flag (0:LYC<>LY, 1:LYC=LY) + self.coincidence_flag = False + + def read(self): + value = 0 + value += int(self.lyc_ly_coincidence) << 7 + value += int(self.h_blank_interrupt) << 6 + value += int(self.oam_interrupt) << 5 + value += int(self.h_blank_interrupt) << 4 + value += int(self.v_blank_interrupt) << 3 + value += int(self.coincidence_flag) << 2 + value += self.mode & 0x03 + return value + + def write(self, value): + pass + + +# ----------------------------------------------------------------------------- + class Video(iMemory): #frames = 0 #frame_skip = 0 @@ -54,6 +89,14 @@ def reset(self): self.cycles = constants.MODE_2_TICKS # used for enabled or disablind window or background + # Bit 7 - LCD Display Enable (0=Off, 1=On) + # Bit 6 - Window Tile Map Display Select (0=9800-9BFF, 1=9C00-9FFF) + # Bit 5 - Window Display Enable (0=Off, 1=On) + # Bit 4 - BG & Window Tile Data Select (0=8800-97FF, 1=8000-8FFF) + # Bit 3 - BG Tile Map Display Select (0=9800-9BFF, 1=9C00-9FFF) + # Bit 2 - OBJ (Sprite) Size (0=8x8, 1=8x16) + # Bit 1 - OBJ (Sprite) Display Enable (0=Off, 1=On) + # Bit 0 - BG Display (for CGB see below) (0=Off, 1=On) self.control = 0x91 self.stat = 2 self.line_y = 0 @@ -77,6 +120,7 @@ self.dirty = True self.vram = [0]*constants.VRAM_SIZE + # Object Attribute Memor self.oam = [0]*constants.OAM_SIZE self.line = [0]* (8+160+8) @@ -174,11 +218,12 @@ def consume_cycles(self): while self.cycles <= 0: - if self.stat == 0: + mode = self.stat & 0x03 + if mode == 0: self.emulate_hblank() - elif self.stat == 1: + elif mode == 1: self.emulate_vblank() - elif self.stat == 2: + elif mode == 2: self.emulate_oam() else: self.emulate_transfer() From cami at codespeak.net Mon May 26 00:56:08 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Mon, 26 May 2008 00:56:08 +0200 (CEST) Subject: [pypy-svn] r55225 - pypy/dist/pypy/lang/gameboy Message-ID: <20080525225608.CB04C168545@codespeak.net> Author: cami Date: Mon May 26 00:56:07 2008 New Revision: 55225 Modified: pypy/dist/pypy/lang/gameboy/cpu.py pypy/dist/pypy/lang/gameboy/gameboy.py pypy/dist/pypy/lang/gameboy/gameboyImplementation.py Log: change videodriver so we have a nice terminal window ;) Modified: pypy/dist/pypy/lang/gameboy/cpu.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/cpu.py (original) +++ pypy/dist/pypy/lang/gameboy/cpu.py Mon May 26 00:56:07 2008 @@ -183,7 +183,7 @@ def c_flag_compare(self, value, compare_and=0x01, reset=False): if reset: self.reset() - print hex(value), hex(compare_and), (value & compare_and) != 0 + #print hex(value), hex(compare_and), (value & compare_and) != 0 self.c_flag = ((value & compare_and) != 0) def h_flag_compare(self, value, a, inverted=False): @@ -383,7 +383,7 @@ def fetch_execute(self): # Execution opCode = self.fetch() - print " fetch exe:", hex(opCode), " " + #print " fetch exe:", hex(opCode), " " #, FETCH_EXECUTE_OP_CODES[opCode].__name__ self.last_fetch_execute_op_code = opCode FETCH_EXECUTE_OP_CODES[opCode](self) @@ -391,11 +391,11 @@ def execute(self, opCode): self.instruction_counter += 1 - print self.instruction_counter, "-"*60 - print "exe: ", hex(opCode), " " + #print self.instruction_counter, "-"*60 + #print "exe: ", hex(opCode), " " #, OP_CODES[opCode].__name__ - print " pc:", hex(self.pc.get()), "sp:", hex(self.sp.get()) - self.print_registers() + #print " pc:", hex(self.pc.get()), "sp:", hex(self.sp.get()) + #self.print_registers() self.last_op_code = opCode OP_CODES[opCode](self) Modified: pypy/dist/pypy/lang/gameboy/gameboy.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/gameboy.py (original) +++ pypy/dist/pypy/lang/gameboy/gameboy.py Mon May 26 00:56:07 2008 @@ -96,7 +96,7 @@ self.joypad.emulate(count) #self.print_cycles() if count == 0: - self.print_cycles() + #self.print_cycles() return 0 ticks -= count return 0 Modified: pypy/dist/pypy/lang/gameboy/gameboyImplementation.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/gameboyImplementation.py (original) +++ pypy/dist/pypy/lang/gameboy/gameboyImplementation.py Mon May 26 00:56:07 2008 @@ -83,8 +83,9 @@ for y in range(self.height): str = "" for x in range(self.width): - str += self.pixel_map(x, y) - RSDL_helper.set_pixel(self.screen, x, y, self.get_pixel_color(x, y)) + if y%2 == 0: + str += self.pixel_map(x, y)*2 + #RSDL_helper.set_pixel(self.screen, x, y, self.get_pixel_color(x, y)) print str; print "-"*60 From santagada at codespeak.net Mon May 26 01:08:50 2008 From: santagada at codespeak.net (santagada at codespeak.net) Date: Mon, 26 May 2008 01:08:50 +0200 (CEST) Subject: [pypy-svn] r55226 - pypy/branch/js-refactoring/pypy/lang/js/test/ecma Message-ID: <20080525230850.2B259169E78@codespeak.net> Author: santagada Date: Mon May 26 01:08:49 2008 New Revision: 55226 Modified: pypy/branch/js-refactoring/pypy/lang/js/test/ecma/conftest.py pypy/branch/js-refactoring/pypy/lang/js/test/ecma/shell.js Log: better error reporting, run with py.test --ecma --tb=short -s Modified: pypy/branch/js-refactoring/pypy/lang/js/test/ecma/conftest.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/test/ecma/conftest.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/test/ecma/conftest.py Mon May 26 01:08:49 2008 @@ -91,10 +91,9 @@ r3 = ctx.resolve_identifier('run_test') w_test_number = W_IntNumber(self.number) result = r3.Call(ctx=ctx, args=[w_test_number]).ToString() + __tracebackhide__ = True if result != "passed": raise Failed(msg=result) - elif result == -1: - py.test.skip() _handling_traceback = False def _getpathlineno(self): Modified: pypy/branch/js-refactoring/pypy/lang/js/test/ecma/shell.js ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/test/ecma/shell.js (original) +++ pypy/branch/js-refactoring/pypy/lang/js/test/ecma/shell.js Mon May 26 01:08:49 2008 @@ -77,7 +77,7 @@ this.actual = a; this.passed = true; this.reason = ""; - print (n, d, e, a); + // print (n, d, e, a); this.bugnumber = BUGNUMBER; this.passed = getTestCaseResult( this.expect, this.actual ); @@ -198,7 +198,7 @@ function run_test(tc) { // try { getTestCaseResult(testcases[tc].expect, testcases[tc].actual); - testcases[tc].reason += ( testcases[tc].passed ) ? "passed" : "wrong value expected: " + testcases[tc].reason += ( testcases[tc].passed ) ? "passed" : testcases[tc].description + " wrong value expected: " +testcases[tc].expect+" but got: "+ testcases[tc].actual; return testcases[tc].reason; // } @@ -219,7 +219,7 @@ } function writeHeaderToLog( string ) { - print( string ); + // print( string ); } /* end of print functions */ From cami at codespeak.net Mon May 26 01:34:04 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Mon, 26 May 2008 01:34:04 +0200 (CEST) Subject: [pypy-svn] r55227 - pypy/dist/pypy/lang/gameboy Message-ID: <20080525233404.9DF79169EF9@codespeak.net> Author: cami Date: Mon May 26 01:34:02 2008 New Revision: 55227 Modified: pypy/dist/pypy/lang/gameboy/gameboyImplementation.py Log: removed string multiplication Modified: pypy/dist/pypy/lang/gameboy/gameboyImplementation.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/gameboyImplementation.py (original) +++ pypy/dist/pypy/lang/gameboy/gameboyImplementation.py Mon May 26 01:34:02 2008 @@ -84,7 +84,8 @@ str = "" for x in range(self.width): if y%2 == 0: - str += self.pixel_map(x, y)*2 + s = self.pixel_map(x, y) + str += s+s #RSDL_helper.set_pixel(self.screen, x, y, self.get_pixel_color(x, y)) print str; @@ -96,7 +97,7 @@ g = (px>>8) & 0xFF r = (px>>16) & 0xFF brightness = 4 * (r+b+g) / (0xFF*3) - return [".", "+", "O", "#", ""][brightness] + return [" ", ".", "+", "#", ""][brightness] def get_pixel_color(self, x, y): return self.pixels[x+self.width*y] From cami at codespeak.net Mon May 26 01:37:02 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Mon, 26 May 2008 01:37:02 +0200 (CEST) Subject: [pypy-svn] r55228 - pypy/dist/pypy/translator/goal Message-ID: <20080525233702.60FD1169EFA@codespeak.net> Author: cami Date: Mon May 26 01:37:01 2008 New Revision: 55228 Modified: pypy/dist/pypy/translator/goal/targetgbimplementation.py pypy/dist/pypy/translator/goal/targetgbrom4.py Log: change targetrom4 to use again the non graphical test rom 4 Modified: pypy/dist/pypy/translator/goal/targetgbimplementation.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetgbimplementation.py (original) +++ pypy/dist/pypy/translator/goal/targetgbimplementation.py Mon May 26 01:37:01 2008 @@ -1,21 +1,27 @@ import os import py +import pdb from pypy.lang.gameboy.gameboyImplementation import GameBoyImplementation ROM_PATH = str(py.magic.autopath().dirpath().dirpath().dirpath())+"/lang/gameboy/rom" -EMULATION_CYCLES = 64 def entry_point(argv=None): - if len(argv) > 1: - filename = argv[1] + if argv is not None and len(argv) > 0: + filename = argv[0] else: - filename = ROM_PATH+"/rom9/rom9.gb" + pos = str(9) + filename = ROM_PATH+"/rom"+pos+"/rom"+pos+".gb" print "loading rom: ", str(filename) gameBoy = GameBoyImplementation() - gameBoy.load_cartridge_file(str(filename)) + try: + gameBoy.load_cartridge_file(str(filename)) + except: + print "Corrupt Cartridge" + gameBoy.load_cartridge_file(str(filename), verify=False) gameBoy.mainLoop() + #pdb.runcall(gameBoy.mainLoop) return 0 @@ -25,4 +31,10 @@ return entry_point, None def test_target(): - entry_point(["boe", ROM_PATH+"/rom4/rom4.gb"]) + entry_point(["b", ROM_PATH+"/rom9/rom9.gb"]) + + + +#from AppKit import NSApplication +#NSApplication.sharedApplication() +#entry_point() Modified: pypy/dist/pypy/translator/goal/targetgbrom4.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetgbrom4.py (original) +++ pypy/dist/pypy/translator/goal/targetgbrom4.py Mon May 26 01:37:01 2008 @@ -5,14 +5,14 @@ ROM_PATH = str(py.magic.autopath().dirpath().dirpath().dirpath())+"/lang/gameboy/rom" -EMULATION_CYCLES = 64 +EMULATION_CYCLES = 1<<24 def entry_point(argv=None): if len(argv) > 1: filename = argv[1] else: - filename = ROM_PATH+"/rom9/rom9.gb" + filename = ROM_PATH+"/rom4/rom4.gb" gameBoy = GameBoy() gameBoy.load_cartridge_file(str(filename)) gameBoy.emulate(EMULATION_CYCLES) From fijal at codespeak.net Mon May 26 02:17:54 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 26 May 2008 02:17:54 +0200 (CEST) Subject: [pypy-svn] r55229 - pypy/dist/pypy/translator/goal Message-ID: <20080526001754.4413E2A8093@codespeak.net> Author: fijal Date: Mon May 26 02:17:53 2008 New Revision: 55229 Modified: pypy/dist/pypy/translator/goal/ann_override.py Log: typo Modified: pypy/dist/pypy/translator/goal/ann_override.py ============================================================================== --- pypy/dist/pypy/translator/goal/ann_override.py (original) +++ pypy/dist/pypy/translator/goal/ann_override.py Mon May 26 02:17:53 2008 @@ -13,7 +13,7 @@ s = s.replace('_', 'x') return s[0].isalpha() and s.isalnum() -# patch - mostly for debugging, to enfore some signatures +# patch - mostly for debugging, to enforce some signatures baseobjspace.ObjSpace.newbool.im_func._annenforceargs_ = Sig(lambda s1,s2: s1, bool) From fijal at codespeak.net Mon May 26 02:18:18 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 26 May 2008 02:18:18 +0200 (CEST) Subject: [pypy-svn] r55230 - pypy/dist/pypy/translator/goal Message-ID: <20080526001818.ECE8F2A805D@codespeak.net> Author: fijal Date: Mon May 26 02:18:18 2008 New Revision: 55230 Modified: pypy/dist/pypy/translator/goal/targetgbimplementation.py Log: First argument is a program name, second is a real argument Modified: pypy/dist/pypy/translator/goal/targetgbimplementation.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetgbimplementation.py (original) +++ pypy/dist/pypy/translator/goal/targetgbimplementation.py Mon May 26 02:18:18 2008 @@ -8,8 +8,8 @@ def entry_point(argv=None): - if argv is not None and len(argv) > 0: - filename = argv[0] + if argv is not None and len(argv) > 1: + filename = argv[1] else: pos = str(9) filename = ROM_PATH+"/rom"+pos+"/rom"+pos+".gb" From fijal at codespeak.net Mon May 26 03:18:05 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 26 May 2008 03:18:05 +0200 (CEST) Subject: [pypy-svn] r55231 - in pypy/dist/pypy/module/zipimport: . test Message-ID: <20080526011805.22B342A8093@codespeak.net> Author: fijal Date: Mon May 26 03:18:03 2008 New Revision: 55231 Modified: pypy/dist/pypy/module/zipimport/__init__.py pypy/dist/pypy/module/zipimport/app_zipimport.py pypy/dist/pypy/module/zipimport/interp_zipimport.py pypy/dist/pypy/module/zipimport/test/test_undocumented.py pypy/dist/pypy/module/zipimport/test/test_zipimport.py Log: Whack, Whack, until it works * Provide _zip_directory_cache as a view on our internal cache * Update test_undocumented to work * Fixes here and there Modified: pypy/dist/pypy/module/zipimport/__init__.py ============================================================================== --- pypy/dist/pypy/module/zipimport/__init__.py (original) +++ pypy/dist/pypy/module/zipimport/__init__.py Mon May 26 03:18:03 2008 @@ -7,10 +7,12 @@ class Module(MixedModule): applevelname = 'zipimport' - interpleveldefs = {'zipimporter':'interp_zipimport.W_ZipImporter'} + interpleveldefs = { + 'zipimporter':'interp_zipimport.W_ZipImporter', + '_zip_directory_cache' : 'space.wrap(interp_zipimport.zip_cache)' + } appleveldefs = { 'ZipImportError' : 'app_zipimport.ZipImportError', - '_zip_directory_cache': 'app_zipimport._zip_directory_cache', } Modified: pypy/dist/pypy/module/zipimport/app_zipimport.py ============================================================================== --- pypy/dist/pypy/module/zipimport/app_zipimport.py (original) +++ pypy/dist/pypy/module/zipimport/app_zipimport.py Mon May 26 03:18:03 2008 @@ -2,4 +2,3 @@ class ZipImportError(ImportError): pass -_zip_directory_cache = {} Modified: pypy/dist/pypy/module/zipimport/interp_zipimport.py ============================================================================== --- pypy/dist/pypy/module/zipimport/interp_zipimport.py (original) +++ pypy/dist/pypy/module/zipimport/interp_zipimport.py Mon May 26 03:18:03 2008 @@ -25,12 +25,108 @@ (True, False, '.pyo'), (False, False, '.py')]) +class W_ZipCache(Wrappable): + def __init__(self): + self.cache = {} + + def get(self, name): + return self.cache[name] + + def set(self, name, w_importer): + self.cache[name] = w_importer + + # -------------- dict-like interface ----------------- + # I don't care about speed of those, they're obscure anyway + # THIS IS A TERRIBLE HACK TO BE CPYTHON COMPATIBLE + + def getitem(self, space, name): + try: + w_zipimporter = self.cache[name] + except KeyError: + raise OperationError(space.w_KeyError, space.wrap(name)) + assert isinstance(w_zipimporter, W_ZipImporter) + dir = w_zipimporter.dir + keys = [k.filename for k in dir.filelist] + w = space.wrap + values = {} + w_d = space.newdict() + for key in keys: + info = dir.NameToInfo[key] + w_values = space.newdict() + space.setitem(w_d, w(key), space.newtuple([ + w(info.filename), w(info.compress_type), w(info.compress_size), + w(info.file_size), w(info.file_offset), w(info.dostime), + w(info.dosdate), w(info.CRC)])) + return w_d + getitem.unwrap_spec = ['self', ObjSpace, str] + + def keys(self, space): + return space.newlist([space.wrap(s) + for s in self.cache.keys()]) + keys.unwrap_spec = ['self', ObjSpace] + + def values(self, space): + keys = self.cache.keys() + values_w = [self.getitem(space, key) for key in keys] + return space.newlist(values_w) + values.unwrap_spec = ['self', ObjSpace] + + def items(self, space): + w = space.wrap + items_w = [space.newtuple([w(key), self.getitem(space, key)]) + for key in self.cache.keys()] + return space.newlist(items_w) + items.unwrap_spec = ['self', ObjSpace] + + def iterkeys(self, space): + return space.iter(self.keys(space)) + iterkeys.unwrap_spec = ['self', ObjSpace] + + def itervalues(self, space): + return space.iter(self.values(space)) + itervalues.unwrap_spec = ['self', ObjSpace] + + def iteritems(self, space): + return space.iter(self.items(space)) + iteritems.unwrap_spec = ['self', ObjSpace] + + def contains(self, space, name): + return space.newbool(name in self.cache) + contains.unwrap_spec = ['self', ObjSpace, str] + + def clear(self, space): + self.cache = {} + clear.unwrap_spec = ['self', ObjSpace] + + def delitem(self, space, name): + del self.cache[name] + delitem.unwrap_spec = ['self', ObjSpace, str] + +W_ZipCache.typedef = TypeDef( + 'zip_dict', + __getitem__ = interp2app(W_ZipCache.getitem), + __contains__ = interp2app(W_ZipCache.contains), + items = interp2app(W_ZipCache.items), + iteritems = interp2app(W_ZipCache.iteritems), + keys = interp2app(W_ZipCache.keys), + iterkeys = interp2app(W_ZipCache.iterkeys), + values = interp2app(W_ZipCache.values), + itervalues = interp2app(W_ZipCache.itervalues), + clear = interp2app(W_ZipCache.clear), + __delitem__ = interp2app(W_ZipCache.delitem), +) + +zip_cache = W_ZipCache() + class W_ZipImporter(Wrappable): def __init__(self, space, name, dir, prefix): self.space = space self.name = name self.dir = dir self.prefix = prefix + self.w_ZipImportError = space.getattr( + space.getbuiltinmodule('zipimport'), + space.wrap('ZipImportError')) def getprefix(space, self): return space.wrap(self.prefix) @@ -111,8 +207,6 @@ except OperationError, e: pass filename = self.mangle(fullname) - w_ZipImportError = space.getattr(space.getbuiltinmodule('zipimport'), - w('ZipImportError')) last_exc = None for compiled, is_package, ext in ENUMERATE_EXTS: try: @@ -133,7 +227,7 @@ w_mods = space.sys.get('modules') space.call_method(w_mods, 'pop', w(fullname), space.w_None) if last_exc: - raise OperationError(space.w_ImportError, last_exc.w_value) + raise OperationError(self.w_ZipImportError, last_exc.w_value) # should never happen I think return space.w_None load_module.unwrap_spec = ['self', ObjSpace, str] @@ -159,8 +253,8 @@ w_source = self.get_data(space, filename + ext) w_code = space.builtin.call('compile', w_source, w(filename + ext), w('exec')) - return w_code - raise OperationError(space.w_ImportError, space.wrap( + return w_code + raise OperationError(space.self.w_ZipImportError, space.wrap( "Cannot find source or code for %s in %s" % (filename, self.name))) get_code.unwrap_spec = ['self', ObjSpace, str] @@ -171,7 +265,7 @@ fname = filename + ext if self.have_modulefile(space, fname): return self.get_data(space, fname) - raise OperationError(space.w_ImportError, space.wrap( + raise OperationError(self.w_ZipImportError, space.wrap( "Cannot find source for %s in %s" % (filename, self.name))) get_source.unwrap_spec = ['self', ObjSpace, str] @@ -180,7 +274,7 @@ for _, is_package, ext in ENUMERATE_EXTS: if self.have_modulefile(space, filename + ext): return space.wrap(is_package) - raise OperationError(space.w_ImportError, space.wrap( + raise OperationError(self.w_ZipImportError, space.wrap( "Cannot find module %s in %s" % (filename, self.name))) is_package.unwrap_spec = ['self', ObjSpace, str] @@ -189,20 +283,9 @@ return space.wrap(self.dir.filename) def descr_new_zipimporter(space, w_type, name): - w_zip_cache = space.getattr(space.getbuiltinmodule('zipimport'), - space.wrap('_zip_directory_cache')) - try: - w_result = space.getitem(w_zip_cache, space.wrap(name)) - if space.is_w(w_result, space.w_None): - raise OperationError(space.w_ImportError, space.wrap( - "Cannot import %s from zipfile, recursion detected or" - "already tried and failed" % (name,))) - return w_result - except OperationError, o: - if not o.match(space, space.w_KeyError): - raise - # XXX think about what to do here - space.setitem(w_zip_cache, space.wrap(name), space.w_None) + w = space.wrap + w_ZipImportError = space.getattr(space.getbuiltinmodule('zipimport'), + w('ZipImportError')) ok = False parts = name.split(os.path.sep) filename = "" # make annotator happy @@ -213,27 +296,35 @@ try: s = os.stat(filename) except OSError: - raise OperationError(space.w_ImportError, space.wrap( + raise OperationError(w_ZipImportError, space.wrap( "Cannot find name %s" % (filename,))) if not stat.S_ISDIR(s.st_mode): ok = True break if not ok: - raise OperationError(space.w_ImportError, space.wrap( + raise OperationError(w_ZipImportError, space.wrap( "Did not find %s to be a valid zippath" % (name,))) - last_elem = filename.split(os.path.sep)[-1] - stop = len(filename)-len(last_elem) - assert stop > 0 - prefix = filename[:stop] + try: + w_result = zip_cache.get(filename) + if w_result is None: + raise OperationError(w_ZipImportError, space.wrap( + "Cannot import %s from zipfile, recursion detected or" + "already tried and failed" % (name,))) + return w_result + except KeyError: + zip_cache.cache[filename] = None try: dir = RZipFile(filename, 'r') except (BadZipfile, OSError): - raise OperationError(space.w_ImportError, space.wrap( + raise OperationError(w_ZipImportError, space.wrap( "%s seems not to be a zipfile" % (filename,))) + prefix = name[len(filename):] + if prefix.startswith(os.sep): + prefix = prefix[1:] w_result = space.wrap(W_ZipImporter(space, name, dir, prefix)) - space.setitem(w_zip_cache, space.wrap(name), w_result) + zip_cache.set(filename, w_result) return w_result - + descr_new_zipimporter.unwrap_spec = [ObjSpace, W_Root, str] W_ZipImporter.typedef = TypeDef( Modified: pypy/dist/pypy/module/zipimport/test/test_undocumented.py ============================================================================== --- pypy/dist/pypy/module/zipimport/test/test_undocumented.py (original) +++ pypy/dist/pypy/module/zipimport/test/test_undocumented.py Mon May 26 03:18:03 2008 @@ -8,26 +8,27 @@ import zipfile from pypy.conftest import gettestobjspace -example_code = 'attr = None' +TESTFN = '@test' -created_paths = set(['_top_level', +created_paths = dict.fromkeys(['_top_level', os.path.join('_pkg', '__init__'), os.path.join('_pkg', 'submodule'), os.path.join('_pkg', '_subpkg', '__init__'), os.path.join('_pkg', '_subpkg', 'submodule') - ]) + ]) -py.test.skip("Completely broken") - -def temp_zipfile(source=True, bytecode=True): +def temp_zipfile(created_paths, source=True, bytecode=True): """Create a temporary zip file for testing. Clears zipimport._zip_directory_cache. """ - zipimport._zip_directory_cache = {} - zip_path = test_support.TESTFN + '.zip' - bytecode_suffix = 'c' if __debug__ else 'o' + import zipimport, os, shutil, zipfile, py_compile + example_code = 'attr = None' + TESTFN = '@test' + zipimport._zip_directory_cache.clear() + zip_path = TESTFN + '.zip' + bytecode_suffix = 'c'# if __debug__ else 'o' zip_file = zipfile.ZipFile(zip_path, 'w') try: for path in created_paths: @@ -57,14 +58,17 @@ shutil.rmtree(directory) else: for suffix in ('.py', '.py' + bytecode_suffix): - test_support.unlink(path + suffix) - test_support.unlink(zip_path) - + if os.path.exists(path + suffix): + os.unlink(path + suffix) + os.unlink(zip_path) class AppTestZipImport: def setup_class(cls): space = gettestobjspace(usemodules=['zipimport', 'zlib', 'rctime']) cls.space = space + source = "():\n" + str(py.code.Source(temp_zipfile).indent()) + "\n return temp_zipfile" + cls.w_temp_zipfile = space.appexec([], source) + cls.w_created_paths = space.wrap(created_paths) def test_inheritance(self): # Should inherit from ImportError. @@ -72,40 +76,42 @@ assert issubclass(zipimport.ZipImportError, ImportError) def test_nonzip(self): + import os + import zipimport # ZipImportError should be raised if a non-zip file is specified. + TESTFN = '@test' + test_file = open(TESTFN, 'w') try: - test_file = open(test_support.TESTFN, 'w') test_file.write("# Test file for zipimport.") try: raises(zipimport.ZipImportError, - zipimport.zipimporter, test_support.TESTFN) + zipimport.zipimporter, TESTFN) finally: - test_support.unlink(test_support.TESTFN) + os.unlink(TESTFN) finally: test_file.close() def test_root(self): + import zipimport, os raises(zipimport.ZipImportError, zipimport.zipimporter, os.sep) def test_direct_path(self): # A zipfile should return an instance of zipimporter. - try: - zip_path = temp_zipfile() + import zipimport + for zip_path in self.temp_zipfile(self.created_paths): zip_importer = zipimport.zipimporter(zip_path) assert isinstance(zip_importer, zipimport.zipimporter) assert zip_importer.archive == zip_path assert zip_importer.prefix == '' assert zip_path in zipimport._zip_directory_cache - finally: - zip_path.close() def test_pkg_path(self): # Thanks to __path__, need to be able to work off of a path with a zip # file at the front and a path for the rest. - try: - zip_path = temp_zipfile() + import zipimport, os + for zip_path in self.temp_zipfile(self.created_paths): prefix = '_pkg' path = os.path.join(zip_path, prefix) zip_importer = zipimport.zipimporter(path) @@ -113,18 +119,14 @@ assert zip_importer.archive == zip_path assert zip_importer.prefix == prefix assert zip_path in zipimport._zip_directory_cache - finally: - zip_path.close() def test_zip_directory_cache(self): # Test that _zip_directory_cache is set properly. # Using a package entry to test using a hard example. - try: - zip_path = temp_zipfile(bytecode=False) + import zipimport, os + for zip_path in self.temp_zipfile(self.created_paths, bytecode=False): importer = zipimport.zipimporter(os.path.join(zip_path, '_pkg')) assert zip_path in zipimport._zip_directory_cache file_set = set(zipimport._zip_directory_cache[zip_path].iterkeys()) - compare_set = set(path + '.py' for path in created_paths) + compare_set = set(path + '.py' for path in self.created_paths) assert file_set == compare_set - finally: - zip_path.close() Modified: pypy/dist/pypy/module/zipimport/test/test_zipimport.py ============================================================================== --- pypy/dist/pypy/module/zipimport/test/test_zipimport.py (original) +++ pypy/dist/pypy/module/zipimport/test/test_zipimport.py Mon May 26 03:18:03 2008 @@ -81,9 +81,9 @@ space.appexec([space.wrap(self)], """(self): self.write_files = [] """) - space.setattr(space.getbuiltinmodule('zipimport'), - space.wrap('_zip_directory_cache'), - space.newdict({})) + w_cache = space.getattr(space.getbuiltinmodule('zipimport'), + space.wrap('_zip_directory_cache')) + space.call_function(space.getattr(w_cache, space.wrap('clear'))) def teardown_method(self, meth): space = self.space @@ -228,7 +228,7 @@ # directly. -exarkun archive = importer.archive allbutlast = self.zipfile.split(os.path.sep)[:-1] - prefix = os.path.sep.join(allbutlast + ['']) + prefix = 'directory' assert archive == self.zipfile assert importer.prefix == prefix From fijal at codespeak.net Mon May 26 03:21:22 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 26 May 2008 03:21:22 +0200 (CEST) Subject: [pypy-svn] r55232 - pypy/dist/pypy/module/zipimport Message-ID: <20080526012122.677F42A805D@codespeak.net> Author: fijal Date: Mon May 26 03:21:20 2008 New Revision: 55232 Modified: pypy/dist/pypy/module/zipimport/interp_zipimport.py Log: Fix translation Modified: pypy/dist/pypy/module/zipimport/interp_zipimport.py ============================================================================== --- pypy/dist/pypy/module/zipimport/interp_zipimport.py (original) +++ pypy/dist/pypy/module/zipimport/interp_zipimport.py Mon May 26 03:21:20 2008 @@ -254,7 +254,7 @@ w_code = space.builtin.call('compile', w_source, w(filename + ext), w('exec')) return w_code - raise OperationError(space.self.w_ZipImportError, space.wrap( + raise OperationError(self.w_ZipImportError, space.wrap( "Cannot find source or code for %s in %s" % (filename, self.name))) get_code.unwrap_spec = ['self', ObjSpace, str] From fijal at codespeak.net Mon May 26 03:36:24 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 26 May 2008 03:36:24 +0200 (CEST) Subject: [pypy-svn] r55233 - pypy/django/tests Message-ID: <20080526013624.B67FF2A8093@codespeak.net> Author: fijal Date: Mon May 26 03:36:22 2008 New Revision: 55233 Modified: pypy/django/tests/conftest.py Log: Make this work also on cpy 2.5 Modified: pypy/django/tests/conftest.py ============================================================================== --- pypy/django/tests/conftest.py (original) +++ pypy/django/tests/conftest.py Mon May 26 03:36:22 2008 @@ -83,8 +83,13 @@ namemethods = getmethods2(s) meth = [] for method in namemethods: + import sys + if sys.version_info[1] == 4: + name = '_TestCase__testMethodName' + else: + name = '_testMethodName' name = (method.__class__.__name__ + '.' + - method._TestCase__testMethodName) + getattr(method, name)) meth.append(name) result += meth else: From fijal at codespeak.net Mon May 26 03:44:08 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 26 May 2008 03:44:08 +0200 (CEST) Subject: [pypy-svn] r55234 - pypy/django/tests Message-ID: <20080526014408.08D622A8093@codespeak.net> Author: fijal Date: Mon May 26 03:44:08 2008 New Revision: 55234 Modified: pypy/django/tests/conftest.py Log: *cough* actually report *any* failure when unittest failed, not just print output and silently eat exception Modified: pypy/django/tests/conftest.py ============================================================================== --- pypy/django/tests/conftest.py (original) +++ pypy/django/tests/conftest.py Mon May 26 03:44:08 2008 @@ -302,8 +302,10 @@ if result.errors: assert len(result.errors) print result.errors[0][1] + py.test.fail("Failed unit test") if result.failures: assert len(result.failures) print result.failures[0][1] + py.test.fail("Failed unit test") if result.failures or result.errors: return 1 From fijal at codespeak.net Mon May 26 05:15:00 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 26 May 2008 05:15:00 +0200 (CEST) Subject: [pypy-svn] r55235 - in pypy/dist/pypy: lib module/sys Message-ID: <20080526031500.82E15169F23@codespeak.net> Author: fijal Date: Mon May 26 05:14:57 2008 New Revision: 55235 Modified: pypy/dist/pypy/lib/imp.py pypy/dist/pypy/module/sys/__init__.py pypy/dist/pypy/module/sys/version.py Log: A hack to present correct magic number at applevel Modified: pypy/dist/pypy/lib/imp.py ============================================================================== --- pypy/dist/pypy/lib/imp.py (original) +++ pypy/dist/pypy/lib/imp.py Mon May 26 05:14:57 2008 @@ -21,7 +21,8 @@ def get_magic(): """Return the magic number for .pyc or .pyo files.""" - return 'm\xf2\r\n' # XXX hard-coded: the magic of Python 2.4.1 + import struct + return struct.pack('L', sys._magic()) def get_suffixes(): """Return a list of (suffix, mode, type) tuples describing the files Modified: pypy/dist/pypy/module/sys/__init__.py ============================================================================== --- pypy/dist/pypy/module/sys/__init__.py (original) +++ pypy/dist/pypy/module/sys/__init__.py Mon May 26 05:14:57 2008 @@ -67,7 +67,9 @@ #'subversion' : added in Python 2.5 'getdefaultencoding' : 'interp_encoding.getdefaultencoding', - 'setdefaultencoding' : 'interp_encoding.setdefaultencoding', + 'setdefaultencoding' : 'interp_encoding.setdefaultencoding', + # XXX hack + '_magic' : 'version._magic', } appleveldefs = { #'displayhook' : 'app.displayhook', Modified: pypy/dist/pypy/module/sys/version.py ============================================================================== --- pypy/dist/pypy/module/sys/version.py (original) +++ pypy/dist/pypy/module/sys/version.py Mon May 26 05:14:57 2008 @@ -63,6 +63,10 @@ d[ver[3]] << 4 | subver) +def _magic(space): + from pypy.module.__builtin__.importing import get_pyc_magic + return space.wrap(get_pyc_magic(space)) + def svn_revision(): "Return the last-changed svn revision number." # NB. we hack the number directly out of the .svn directory to avoid From fijal at codespeak.net Mon May 26 05:32:21 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 26 May 2008 05:32:21 +0200 (CEST) Subject: [pypy-svn] r55236 - in pypy/dist/pypy/module/zipimport: . test Message-ID: <20080526033221.813D1169F42@codespeak.net> Author: fijal Date: Mon May 26 05:32:18 2008 New Revision: 55236 Modified: pypy/dist/pypy/module/zipimport/interp_zipimport.py pypy/dist/pypy/module/zipimport/test/test_zipimport.py Log: Update enough to make more cpython's test suite pass. Modified: pypy/dist/pypy/module/zipimport/interp_zipimport.py ============================================================================== --- pypy/dist/pypy/module/zipimport/interp_zipimport.py (original) +++ pypy/dist/pypy/module/zipimport/interp_zipimport.py Mon May 26 05:32:18 2008 @@ -131,8 +131,7 @@ def getprefix(space, self): return space.wrap(self.prefix) - def import_py_file(self, space, modname, filename, w_buf, pkgpath): - buf = space.str_w(w_buf) + 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 + filename @@ -142,14 +141,14 @@ space.setattr(w_mod, w('__loader__'), space.wrap(self)) return result - def check_newer_pyfile(self, space, filename, timestamp): + def _parse_mtime(self, space, filename): w = space.wrap try: info = self.dir.getinfo(filename) t = info.date_time except (BadZipfile, KeyError): # in either case, this is a fallback - return False + return 0 else: w_mktime = space.getattr(space.getbuiltinmodule('time'), w('mktime')) @@ -159,15 +158,27 @@ all = [w(t[0]), w(t[1]), w(t[2]), w(t[3]), w(t[4]), w(t[5]), w(0), w(1), w(-1)] mtime = int(space.float_w(space.call_function(w_mktime, space.newtuple(all)))) - return mtime > timestamp + return mtime + + def check_newer_pyfile(self, space, filename, timestamp): + mtime = self._parse_mtime(space, filename) + if mtime == 0: + return False + return mtime > timestamp - def import_pyc_file(self, space, modname, filename, w_buf, pkgpath): + def check_compatible_mtime(self, space, filename, timestamp): + mtime = self._parse_mtime(space, filename) + if mtime == 0 or mtime != (timestamp & (~1)): + return False + return True + + def import_pyc_file(self, space, modname, filename, buf, pkgpath): w = space.wrap - buf = space.str_w(w_buf) magic = importing._get_long(buf[:4]) timestamp = importing._get_long(buf[4:8]) - if self.check_newer_pyfile(space, filename[:-1], timestamp): - return self.import_py_file(space, modname, filename[:-1], w_buf, + if (self.check_newer_pyfile(space, filename[:-1], timestamp) or + not self.check_compatible_mtime(space, filename, timestamp)): + return self.import_py_file(space, modname, filename[:-1], buf, pkgpath) buf = buf[8:] # XXX ugly copy, should use sequential read instead w_mod = w(Module(space, w(modname))) @@ -209,22 +220,26 @@ filename = self.mangle(fullname) last_exc = None for compiled, is_package, ext in ENUMERATE_EXTS: + fname = filename + ext try: - fname = filename + ext - w_buf = self.get_data(space, fname) + buf = self.dir.read(fname) + except (KeyError, OSError): + pass + else: if is_package: pkgpath = self.name else: pkgpath = None - if compiled: - return self.import_pyc_file(space, fullname, fname, - w_buf, pkgpath) - else: - return self.import_py_file(space, fullname, fname, - w_buf, pkgpath) - except OperationError, e: - last_exc = e - w_mods = space.sys.get('modules') + try: + if compiled: + return self.import_pyc_file(space, fullname, fname, + buf, pkgpath) + else: + return self.import_py_file(space, fullname, fname, + buf, pkgpath) + except OperationError, e: + last_exc = e + w_mods = space.sys.get('modules') space.call_method(w_mods, 'pop', w(fullname), space.w_None) if last_exc: raise OperationError(self.w_ZipImportError, last_exc.w_value) Modified: pypy/dist/pypy/module/zipimport/test/test_zipimport.py ============================================================================== --- pypy/dist/pypy/module/zipimport/test/test_zipimport.py (original) +++ pypy/dist/pypy/module/zipimport/test/test_zipimport.py Mon May 26 05:32:18 2008 @@ -135,6 +135,7 @@ def test_pyc(self): import sys, os self.writefile(self, "uuu.pyc", self.test_pyc) + self.writefile(self, "uuu.py", "def f(x): return x") mod = __import__('uuu', globals(), locals(), []) expected = { '__doc__' : None, From antocuni at codespeak.net Mon May 26 10:09:46 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 26 May 2008 10:09:46 +0200 (CEST) Subject: [pypy-svn] r55237 - in pypy/branch/oo-jit/pypy/jit: rainbow rainbow/test timeshifter Message-ID: <20080526080946.014BA169ED6@codespeak.net> Author: antocuni Date: Mon May 26 10:09:45 2008 New Revision: 55237 Modified: pypy/branch/oo-jit/pypy/jit/rainbow/test/test_promotion.py pypy/branch/oo-jit/pypy/jit/rainbow/typesystem.py pypy/branch/oo-jit/pypy/jit/timeshifter/rtimeshift.py Log: start porting promotion tests to ootype Modified: pypy/branch/oo-jit/pypy/jit/rainbow/test/test_promotion.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/rainbow/test/test_promotion.py (original) +++ pypy/branch/oo-jit/pypy/jit/rainbow/test/test_promotion.py Mon May 26 10:09:45 2008 @@ -4,11 +4,11 @@ from pypy.jit.rainbow.test.test_interpreter import StopAtXPolicy from pypy.jit.rainbow.test.test_interpreter import P_NOVIRTUAL from pypy.jit.rainbow.test.test_vlist import P_OOPSPEC +from pypy.jit.rainbow.test.test_interpreter import OOTypeMixin from pypy.rlib.jit import hint from pypy.rpython.module.support import LLSupport -class TestPromotion(InterpretationTest): - type_system = "lltype" +class BaseTestPromotion(InterpretationTest): small = True def test_simple_promotion(self): @@ -461,3 +461,22 @@ res = self.interpret(ll_function, [4, 7], [], policy=P_NOVIRTUAL) assert res == 11 self.check_insns(int_add=0) + +class TestLLType(BaseTestPromotion): + type_system = "lltype" + +class TestOOType(OOTypeMixin, BaseTestPromotion): + type_system = "ootype" + + def skip(self): + py.test.skip('in progress') + + test_promote_after_call = skip + test_promote_after_yellow_call = skip + test_merge_then_promote = skip + test_vstruct_unfreeze = skip + test_more_promotes = skip + test_remembers_across_mp = skip + test_virtual_list_copy = skip + test_raise_result_mixup = skip + test_raise_result_mixup_some_more = skip Modified: pypy/branch/oo-jit/pypy/jit/rainbow/typesystem.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/rainbow/typesystem.py (original) +++ pypy/branch/oo-jit/pypy/jit/rainbow/typesystem.py Mon May 26 10:09:45 2008 @@ -28,6 +28,7 @@ name = 'lltype' ROOT_TYPE = llmemory.Address + BASE_OBJ_TYPE = base_ptr_lltype() NULL_OBJECT = base_ptr_lltype()._defl() cast_instance_to_base_ptr = staticmethod(cast_instance_to_base_ptr) @@ -54,10 +55,15 @@ FUNCPTRTYPE = lltype.Ptr(FUNCTYPE) return FUNCTYPE, FUNCPTRTYPE + def PromotionPoint(self, flexswitch, incoming_gv, promotion_path): + from pypy.jit.timeshifter.rtimeshift import PromotionPointLLType + return PromotionPointLLType(flexswitch, incoming_gv, promotion_path) + class OOTypeHelper(TypeSystemHelper): name = 'ootype' ROOT_TYPE = ootype.Object + BASE_OBJ_TYPE = base_obj_ootype() NULL_OBJECT = base_obj_ootype()._defl() cast_instance_to_base_ptr = staticmethod(cast_instance_to_base_obj) @@ -84,6 +90,10 @@ FUNCTYPE = ootype.StaticMethod(ARGS, RESULT) return FUNCTYPE, FUNCTYPE + def PromotionPoint(self, flexswitch, incoming_gv, promotion_path): + from pypy.jit.timeshifter.rtimeshift import PromotionPointOOType + return PromotionPointOOType(flexswitch, incoming_gv, promotion_path) + llhelper = LLTypeHelper() oohelper = OOTypeHelper() Modified: pypy/branch/oo-jit/pypy/jit/timeshifter/rtimeshift.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/timeshifter/rtimeshift.py (original) +++ pypy/branch/oo-jit/pypy/jit/timeshifter/rtimeshift.py Mon May 26 10:09:45 2008 @@ -6,7 +6,7 @@ from pypy.jit.timeshifter.greenkey import newgreendict, empty_key from pypy.rlib.objectmodel import we_are_translated from pypy.rlib.unroll import unrolling_iterable -from pypy.rpython.annlowlevel import cachedtype, base_ptr_lltype +from pypy.rpython.annlowlevel import cachedtype, base_ptr_lltype, base_obj_ootype from pypy.rpython.annlowlevel import cast_instance_to_base_ptr from pypy.rpython.annlowlevel import cast_base_ptr_to_instance, llhelper @@ -680,7 +680,6 @@ else: self.mergesleft = parent_mergesleft - class PromotionPoint(object): def __init__(self, flexswitch, incoming_gv, promotion_path): assert promotion_path is not None @@ -688,10 +687,16 @@ self.incoming_gv = incoming_gv self.promotion_path = promotion_path +class PromotionPointLLType(PromotionPoint): + # hack for testing: make the llinterpreter believe this is a Ptr to base # instance _TYPE = base_ptr_lltype() +class PromotionPointOOType(PromotionPoint): + _TYPE = base_obj_ootype() + + class AbstractPromotionPath(object): cut_limit = False @@ -813,7 +818,7 @@ ll_continue_compilation._debugexc = True ts = interpreter.ts - FUNCTYPE, FUNCPTRTYPE = ts.get_FuncType([base_ptr_lltype(), ERASED], lltype.Void) + FUNCTYPE, FUNCPTRTYPE = ts.get_FuncType([ts.BASE_OBJ_TYPE, ERASED], lltype.Void) self.FUNCPTRTYPE = FUNCPTRTYPE self.sigtoken = interpreter.rgenop.sigToken(FUNCTYPE) @@ -843,8 +848,8 @@ if resuming is None: jitstate.curbuilder = default_builder # default case of the switch: - pm = PromotionPoint(flexswitch, incoming_gv, - jitstate.promotion_path) + pm = jitstate.ts.PromotionPoint(flexswitch, incoming_gv, + jitstate.promotion_path) #debug_print(lltype.Void, "PROMOTE") ll_pm = _cast_promotion_point_to_base_ptr(jitstate, pm) gv_pm = default_builder.rgenop.genconst(ll_pm) From antocuni at codespeak.net Mon May 26 10:16:49 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 26 May 2008 10:16:49 +0200 (CEST) Subject: [pypy-svn] r55238 - in pypy/branch/oo-jit/pypy/jit/codegen: cli cli/test i386/test llvm/test Message-ID: <20080526081649.5687D169ED9@codespeak.net> Author: antocuni Date: Mon May 26 10:16:47 2008 New Revision: 55238 Added: pypy/branch/oo-jit/pypy/jit/codegen/cli/test/__init__.py (contents, props changed) pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_promotion.py (contents, props changed) Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/operation.py pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_interpreter.py pypy/branch/oo-jit/pypy/jit/codegen/i386/test/test_genc_promotion.py pypy/branch/oo-jit/pypy/jit/codegen/llvm/test/test_genc_promotion.py Log: "port" promotion tests to cli (they are all skipped so far) Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/operation.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/codegen/cli/operation.py (original) +++ pypy/branch/oo-jit/pypy/jit/codegen/cli/operation.py Mon May 26 10:16:47 2008 @@ -169,7 +169,7 @@ self.fieldinfo = clitype.GetField(fieldname) def restype(self): - return self.fieldinfo.FieldType + return self.fieldinfo.get_FieldType() def emit(self): self.gv_obj.load(self.builder) Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py (original) +++ pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py Mon May 26 10:16:47 2008 @@ -261,6 +261,15 @@ return SigToken(args, res, funcclass) @staticmethod + def erasedType(T): + if isinstance(T, lltype.Primitive): + return lltype.Signed + elif isinstance(T, ootype.OOType): + return ootype.Object + else: + assert 0, "XXX not implemented" + + @staticmethod @specialize.memo() def methToken(TYPE, methname): return methname #XXX Added: pypy/branch/oo-jit/pypy/jit/codegen/cli/test/__init__.py ============================================================================== Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_interpreter.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_interpreter.py (original) +++ pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_interpreter.py Mon May 26 10:16:47 2008 @@ -3,12 +3,9 @@ from pypy.jit.codegen.dump.rgenop import RDumpGenOp from pypy.jit.rainbow.test.test_interpreter import TestOOType as RainbowTest -class TestRainbowCli(RainbowTest): +class CliMixin(object): RGenOp = RCliGenOp - # for the individual tests see - # ====> ../../../rainbow/test/test_interpreter.py - def _invoke(self, generated, residualargs): # mono sucks; if we call the generated function directly, @@ -34,6 +31,12 @@ def check_insns(self, expected=None, **counts): "Cannot check instructions in the generated assembler." +class TestRainbowCli(CliMixin, RainbowTest): + + # for the individual tests see + # ====> ../../../rainbow/test/test_interpreter.py + + def test_simple_opt_const_propagation1(self): py.test.skip('mono crash') Added: pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_promotion.py ============================================================================== --- (empty file) +++ pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_promotion.py Mon May 26 10:16:47 2008 @@ -0,0 +1,33 @@ +import py +from pypy.jit.codegen.cli.test.test_interpreter import CliMixin +from pypy.jit.rainbow.test.test_promotion import TestOOType as PromotionTest + +class TestPromotionCli(CliMixin, PromotionTest): + + # for the individual tests see + # ====> ../../../rainbow/test/test_promotion.py + + def skip(self): + py.test.skip('in progress') + + test_simple_promotion = skip + test_many_promotions = skip + test_promote_inside_call = skip + test_promote_inside_call2 = skip + test_two_promotions = skip + test_mixed_merges = skip + test_green_across_global_mp = skip + test_promote_bug_1 = skip + test_exception_after_promotion = skip + test_promote_in_yellow_call = skip + test_more_promote_in_yellow_call = skip + test_two_promotions_in_call = skip + test_more_promotes = skip + test_raise_result_mixup_some_more = skip + test_raise_result_mixup = skip + test_remembers_across_mp = skip + test_promote_after_yellow_call = skip + test_virtual_list_copy = skip + test_vstruct_unfreeze = skip + test_promote_after_call = skip + test_merge_then_promote = skip Modified: pypy/branch/oo-jit/pypy/jit/codegen/i386/test/test_genc_promotion.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/codegen/i386/test/test_genc_promotion.py (original) +++ pypy/branch/oo-jit/pypy/jit/codegen/i386/test/test_genc_promotion.py Mon May 26 10:16:47 2008 @@ -4,7 +4,7 @@ from pypy.jit.codegen.i386.test.test_genc_ts import I386TimeshiftingTestMixin class TestPromotion(I386TimeshiftingTestMixin, - test_promotion.TestPromotion): + test_promotion.TestLLType): # for the individual tests see # ====> ../../../timeshifter/test/test_promotion.py Modified: pypy/branch/oo-jit/pypy/jit/codegen/llvm/test/test_genc_promotion.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/codegen/llvm/test/test_genc_promotion.py (original) +++ pypy/branch/oo-jit/pypy/jit/codegen/llvm/test/test_genc_promotion.py Mon May 26 10:16:47 2008 @@ -5,7 +5,7 @@ py.test.skip("WIP") class TestPromotion(LLVMTimeshiftingTestMixin, - test_promotion.TestPromotion): + test_promotion.TestLLType): # for the individual tests see # ====> ../../../timeshifter/test/test_promotion.py From antocuni at codespeak.net Mon May 26 10:19:58 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 26 May 2008 10:19:58 +0200 (CEST) Subject: [pypy-svn] r55239 - pypy/branch/oo-jit/pypy/jit/tl Message-ID: <20080526081958.BB453169ED9@codespeak.net> Author: antocuni Date: Mon May 26 10:19:57 2008 New Revision: 55239 Added: pypy/branch/oo-jit/pypy/jit/tl/targettlr.py (contents, props changed) Log: add a target to compile tlr with jit Added: pypy/branch/oo-jit/pypy/jit/tl/targettlr.py ============================================================================== --- (empty file) +++ pypy/branch/oo-jit/pypy/jit/tl/targettlr.py Mon May 26 10:19:57 2008 @@ -0,0 +1,51 @@ +import py +py.magic.autopath() +from pypy.jit.tl.tlr import interpret +from pypy.jit.codegen.hlinfo import highleveljitinfo + + +def entry_point(args): + """Main entry point of the stand-alone executable: + takes a list of strings and returns the exit code. + """ + # store args[0] in a place where the JIT log can find it (used by + # viewcode.py to know the executable whose symbols it should display) + highleveljitinfo.sys_executable = args[0] + if len(args) < 3: + print "Usage: %s filename x" % (args[0],) + return 2 + filename = args[1] + x = int(args[2]) + bytecode = load_bytecode(filename) + res = interpret(bytecode, x) + print res + return 0 + +def load_bytecode(filename): + from pypy.rlib.streamio import open_file_as_stream + f = open_file_as_stream(filename) + bytecode = f.readall() + f.close() + return bytecode + +def target(driver, args): + return entry_point, None + +# ____________________________________________________________ + +from pypy.jit.hintannotator.policy import HintAnnotatorPolicy + +class MyHintAnnotatorPolicy(HintAnnotatorPolicy): + novirtualcontainer = True + oopspec = True + +def portal(driver): + """Return the 'portal' function, and the hint-annotator policy. + The portal is the function that gets patched with a call to the JIT + compiler. + """ + return interpret, MyHintAnnotatorPolicy() + +if __name__ == '__main__': + import sys + sys.exit(entry_point(sys.argv)) From antocuni at codespeak.net Mon May 26 10:55:01 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 26 May 2008 10:55:01 +0200 (CEST) Subject: [pypy-svn] r55240 - pypy/branch/oo-jit/pypy/jit/rainbow/test Message-ID: <20080526085501.A587C169ED6@codespeak.net> Author: antocuni Date: Mon May 26 10:55:00 2008 New Revision: 55240 Modified: pypy/branch/oo-jit/pypy/jit/rainbow/test/test_vlist.py Log: add a new test Modified: pypy/branch/oo-jit/pypy/jit/rainbow/test/test_vlist.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/rainbow/test/test_vlist.py (original) +++ pypy/branch/oo-jit/pypy/jit/rainbow/test/test_vlist.py Mon May 26 10:55:00 2008 @@ -1,4 +1,5 @@ import py +from pypy.rpython.test.tool import LLRtypeMixin, OORtypeMixin from pypy.jit.hintannotator.policy import HintAnnotatorPolicy from pypy.jit.rainbow.test.test_interpreter import InterpretationTest, P_OOPSPEC from pypy.jit.rainbow.test.test_interpreter import OOTypeMixin @@ -7,7 +8,6 @@ class VListTest(InterpretationTest): - type_system = "lltype" def test_vlist(self): def ll_function(): @@ -88,6 +88,20 @@ res = self.interpret(ll_function, [0], [], policy=P_OOPSPEC) assert res == 0 + force_fixed_insns = None + def test_force_fixed(self): + def ll_function(flag): + lst = [0, 0, 0] + if flag: + lst[0] = 42 + else: + lst[0] = 1 + return lst + res = self.interpret(ll_function, [True], [], policy=P_OOPSPEC) + res = self.ll_to_list(res) + assert res == [42, 0, 0] + self.check_insns(self.force_fixed_insns) + def test_oop_vlist(self): def ll_function(): lst = [3, 5] @@ -201,8 +215,10 @@ assert res == -7 -class TestOOType(OOTypeMixin, VListTest): +class TestOOType(OOTypeMixin, OORtypeMixin, VListTest): type_system = "ootype" + force_fixed_insns = {'oonewarray': 1, 'oosend': 3} -class TestLLType(VListTest): +class TestLLType(LLRtypeMixin, VListTest): type_system = "lltype" + force_fixed_insns = {'direct_call': 4} From antocuni at codespeak.net Mon May 26 12:42:54 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 26 May 2008 12:42:54 +0200 (CEST) Subject: [pypy-svn] r55241 - in pypy/branch/oo-jit/pypy/jit: rainbow/test timeshifter Message-ID: <20080526104254.1383B169EF3@codespeak.net> Author: antocuni Date: Mon May 26 12:42:52 2008 New Revision: 55241 Modified: pypy/branch/oo-jit/pypy/jit/rainbow/test/test_portal.py pypy/branch/oo-jit/pypy/jit/timeshifter/oop.py Log: if oop_newlist gets an oopdesc that can be either for a fixed or non fixed size list, the annotator complains that do_call doesn't receive enough arguments. It's right, but I think this code is never called in that case. Not sure if it's needed or not, but at least now the test passes. Modified: pypy/branch/oo-jit/pypy/jit/rainbow/test/test_portal.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/rainbow/test/test_portal.py (original) +++ pypy/branch/oo-jit/pypy/jit/rainbow/test/test_portal.py Mon May 26 12:42:52 2008 @@ -602,6 +602,26 @@ assert res == ll_function() self.check_insns({}) + def test_force_fixed_vlist(self): + def a(flag): + lst = [0, 0, 0] + if flag: + lst[0] = 20 + return lst[0] + + def b(flag): + lst = [0] + if flag: + lst.append(22) + return lst[-1] + + def ll_function(): + from pypy.rlib.nonconst import NonConstant + flag = NonConstant(True) + return a(flag) + b(flag) + res = self.timeshift_from_portal(ll_function, ll_function, []) + assert res == 42 + self.check_insns({}) class TestPortalOOType(BaseTestPortal): Modified: pypy/branch/oo-jit/pypy/jit/timeshifter/oop.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/timeshifter/oop.py (original) +++ pypy/branch/oo-jit/pypy/jit/timeshifter/oop.py Mon May 26 12:42:52 2008 @@ -243,10 +243,7 @@ class NewOopSpecDesc(AbstractOopSpecDesc): def _setup_oopdesc(self, RGenOp, TYPE): self.SELFTYPE = TYPE - self.ARGS = [] self.RESULT = TYPE - self.OOPARGTYPES = [] - self.residualargsources = [] self.typename = TYPE.oopspec_name self.method = 'oop_new%s' % self.typename self.is_method = False @@ -258,9 +255,15 @@ if isinstance(TYPE, ootype.Array): def allocate(length): return ootype.oonewarray(TYPE, length) + self.ARGS = [ootype.Signed] + self.OOPARGTYPES = [ootype.Signed] + self.residualargsources = [0] self.fnptr = self.rtyper.annotate_helper_fn(allocate, [ootype.Signed]) else: + self.ARGS = [] + self.OOPARGTYPES = [] + self.residualargsources = [] def allocate(): return ootype.new(TYPE) self.fnptr = self.rtyper.annotate_helper_fn(allocate, []) From antocuni at codespeak.net Mon May 26 14:32:56 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 26 May 2008 14:32:56 +0200 (CEST) Subject: [pypy-svn] r55245 - pypy/branch/oo-jit/pypy/translator Message-ID: <20080526123256.A18822A80A7@codespeak.net> Author: antocuni Date: Mon May 26 14:32:53 2008 New Revision: 55245 Modified: pypy/branch/oo-jit/pypy/translator/driver.py Log: make sure task_rainbow is done at the right time Modified: pypy/branch/oo-jit/pypy/translator/driver.py ============================================================================== --- pypy/branch/oo-jit/pypy/translator/driver.py (original) +++ pypy/branch/oo-jit/pypy/translator/driver.py Mon May 26 14:32:53 2008 @@ -505,7 +505,9 @@ backend_optimizations(self.translator) # task_backendopt_ootype = taskdef(task_backendopt_ootype, - [OOTYPE], "ootype back-end optimisations") + [OOTYPE, + '??rainbow_ootype'], + "ootype back-end optimisations") OOBACKENDOPT = 'backendopt_ootype' From antocuni at codespeak.net Mon May 26 14:34:41 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 26 May 2008 14:34:41 +0200 (CEST) Subject: [pypy-svn] r55246 - in pypy/branch/oo-jit/pypy: annotation jit/codegen/cli Message-ID: <20080526123441.8BA372A80A2@codespeak.net> Author: antocuni Date: Mon May 26 14:34:39 2008 New Revision: 55246 Modified: pypy/branch/oo-jit/pypy/annotation/builtin.py pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py Log: hack until I can run translate.py -b cli --jit targettlr.py Modified: pypy/branch/oo-jit/pypy/annotation/builtin.py ============================================================================== --- pypy/branch/oo-jit/pypy/annotation/builtin.py (original) +++ pypy/branch/oo-jit/pypy/annotation/builtin.py Mon May 26 14:34:39 2008 @@ -9,7 +9,7 @@ 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 SomeOOObject +from pypy.annotation.model import SomeOOObject, SomeOOStaticMeth from pypy.annotation.model import annotation_to_lltype, lltype_to_annotation, ll_to_annotation from pypy.annotation.model import add_knowntypedata from pypy.annotation.model import s_ImpossibleValue @@ -576,12 +576,12 @@ TYPE = T.const if TYPE is ootype.Object: return SomeOOObject() - elif isinstance(TYPE, ootype.Instance): - return SomeOOInstance(TYPE) - elif isinstance(TYPE, ootype.Record): - return SomeOOInstance(TYPE) # XXX: SomeOORecord? + elif TYPE is ootype.Class: + return SomeOOClass(T) elif isinstance(TYPE, ootype.StaticMethod): return SomeOOStaticMeth(TYPE) + elif isinstance(TYPE, ootype.OOType): + return SomeOOInstance(TYPE) else: raise AnnotatorError, 'Cannot cast Object to %s' % TYPE Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py (original) +++ pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py Mon May 26 14:34:39 2008 @@ -99,6 +99,8 @@ def revealconst(self, T): if T is ootype.Object: return ootype.NULL # XXX? + elif isinstance(T, ootype.OOType): + return ootype.null(T) # XXX return lltype.cast_primitive(T, self.value) def getCliType(self): @@ -389,6 +391,15 @@ def genop_oosetfield(self, fieldtoken, gv_obj, gv_value): return self.branches[0].genop_oosetfield(fieldtoken, gv_obj, gv_value) + def genop_oonewarray(self, alloctoken, gv_length): + raise NotImplementedError + + def genop_oononnull(self, gv_obj): + raise NotImplementedError + + def genop_ooisnull(self, gv_obj): + raise NotImplementedError + def end(self): # render all the pending branches for branchbuilder in self.branches: From afa at codespeak.net Mon May 26 17:22:56 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Mon, 26 May 2008 17:22:56 +0200 (CEST) Subject: [pypy-svn] r55248 - pypy/dist/pypy/module/rctime Message-ID: <20080526152256.719DC2A80A5@codespeak.net> Author: afa Date: Mon May 26 17:22:53 2008 New Revision: 55248 Modified: pypy/dist/pypy/module/rctime/app_time.py Log: With this tiny change, os.pyc is no more frozen and embedded inside pypy-c, if --allworkingmodules is used. Modified: pypy/dist/pypy/module/rctime/app_time.py ============================================================================== --- pypy/dist/pypy/module/rctime/app_time.py (original) +++ pypy/dist/pypy/module/rctime/app_time.py Mon May 26 17:22:53 2008 @@ -1,10 +1,7 @@ # NOT_RPYTHON -import os from _structseq import structseqtype, structseqfield -_POSIX = os.name == "posix" - class struct_time: __metaclass__ = structseqtype __module__ = 'time' From fijal at codespeak.net Mon May 26 19:08:15 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 26 May 2008 19:08:15 +0200 (CEST) Subject: [pypy-svn] r55251 - in pypy/dist/pypy: objspace/std rlib rlib/test rpython rpython/lltypesystem rpython/lltypesystem/test rpython/memory rpython/memory/gc rpython/memory/gc/test rpython/memory/gctransform rpython/memory/test rpython/ootypesystem rpython/test translator/c/src translator/c/test Message-ID: <20080526170815.9F2F62A80AD@codespeak.net> Author: fijal Date: Mon May 26 19:08:10 2008 New Revision: 55251 Modified: pypy/dist/pypy/objspace/std/formatting.py pypy/dist/pypy/rlib/objectmodel.py pypy/dist/pypy/rlib/rstring.py pypy/dist/pypy/rlib/test/test_objectmodel.py pypy/dist/pypy/rpython/llinterp.py pypy/dist/pypy/rpython/lltypesystem/llmemory.py pypy/dist/pypy/rpython/lltypesystem/lloperation.py pypy/dist/pypy/rpython/lltypesystem/rbuilder.py pypy/dist/pypy/rpython/lltypesystem/rlist.py pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py pypy/dist/pypy/rpython/memory/gc/base.py pypy/dist/pypy/rpython/memory/gc/generation.py pypy/dist/pypy/rpython/memory/gc/hybrid.py pypy/dist/pypy/rpython/memory/gc/test/test_direct.py pypy/dist/pypy/rpython/memory/gctransform/boehm.py pypy/dist/pypy/rpython/memory/gctransform/framework.py pypy/dist/pypy/rpython/memory/gctransform/transform.py pypy/dist/pypy/rpython/memory/gcwrapper.py pypy/dist/pypy/rpython/memory/support.py pypy/dist/pypy/rpython/memory/test/test_gc.py pypy/dist/pypy/rpython/memory/test/test_support.py pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py pypy/dist/pypy/rpython/ootypesystem/rbuilder.py pypy/dist/pypy/rpython/ootypesystem/rlist.py pypy/dist/pypy/rpython/rbuilder.py pypy/dist/pypy/rpython/rlist.py pypy/dist/pypy/rpython/test/test_rlist.py pypy/dist/pypy/translator/c/src/mem.h pypy/dist/pypy/translator/c/test/test_boehm.py pypy/dist/pypy/translator/c/test/test_newgc.py Log: (arigo, fijal) Merge the hybrid-io branch by svn merge -r 54649:HEAD http://codespeak.net/svn/pypy/branch/hybrid-io/pypy . This branch covers: * Removal of rlib.objectmodel.newlist, as part of decluttering * Fixes for string builder, so it can it variable length as argument * More tests * GC fixes * raw_realloc implementation * hybrid gc can now realloc * hybrid gc can now malloc nonmovable * write_barrier doesn't need old pointer for now * hybrid gc manages separate stack for resizable pointers This branch is not finished, but reason for merging it is that io-improvements was merged in somewhat inconsistent state. This will hopefully fix problems (although some still exist) Modified: pypy/dist/pypy/objspace/std/formatting.py ============================================================================== --- pypy/dist/pypy/objspace/std/formatting.py (original) +++ pypy/dist/pypy/objspace/std/formatting.py Mon May 26 19:08:10 2008 @@ -256,10 +256,11 @@ return result def format(self): + lgt = len(self.fmt) + 4 * len(self.values_w) + 10 if do_unicode: - result = UnicodeBuilder() + result = UnicodeBuilder(lgt) else: - result = StringBuilder() + result = StringBuilder(lgt) self.result = result while True: # fast path: consume as many characters as possible Modified: pypy/dist/pypy/rlib/objectmodel.py ============================================================================== --- pypy/dist/pypy/rlib/objectmodel.py (original) +++ pypy/dist/pypy/rlib/objectmodel.py Mon May 26 19:08:10 2008 @@ -349,25 +349,3 @@ self.dic = dic self.key = key self.hash = hash - -# ------------------------- optimization hints ------------------------------ - -def newlist(sizehint=0): - return [] - -class Entry(ExtRegistryEntry): - _about_ = newlist - - def compute_result_annotation(self, s_sizehint): - return self.bookkeeper.newlist() - - def specialize_call(self, orig_hop, i_sizehint=None): - from pypy.rpython.rlist import rtype_newlist - from pypy.rpython.lltypesystem import lltype - # fish a bit hop - hop = orig_hop.copy() - v = hop.args_v[0] - r, s = hop.r_s_popfirstarg() - if s.is_constant(): - v = hop.inputconst(r, s.const) - return rtype_newlist(hop, v_sizehint=v) Modified: pypy/dist/pypy/rlib/rstring.py ============================================================================== --- pypy/dist/pypy/rlib/rstring.py (original) +++ pypy/dist/pypy/rlib/rstring.py Mon May 26 19:08:10 2008 @@ -3,7 +3,10 @@ """ from pypy.rpython.extregistry import ExtRegistryEntry -from pypy.rpython.annlowlevel import llhelper +from pypy.annotation.model import SomeObject, SomeString, s_None,\ + SomeChar, SomeInteger, SomeUnicodeCodePoint, SomeUnicodeString + +# -------------- public API --------------------------------- INIT_SIZE = 100 # XXX tweak @@ -28,17 +31,67 @@ def build(self): return u''.join(self.l) +# ------------------------------------------------------------ +# ----------------- implementation details ------------------- +# ------------------------------------------------------------ + +class SomeStringBuilder(SomeObject): + def method_append(self, s_str): + assert isinstance(s_str, (SomeString, SomeChar)) + return s_None + + def method_append_slice(self, s_str, s_start, s_end): + assert isinstance(s_str, SomeString) + assert isinstance(s_start, SomeInteger) + assert isinstance(s_end, SomeInteger) + assert s_start.nonneg + assert s_end.nonneg + return s_None + + def method_append_multiple_char(self, s_char, s_times): + assert isinstance(s_char, SomeChar) + assert isinstance(s_times, SomeInteger) + assert s_times.nonneg + return s_None + + def method_build(self): + return SomeString() + + def rtyper_makerepr(self, rtyper): + return rtyper.type_system.rbuilder.stringbuilder_repr + +class SomeUnicodeBuilder(SomeObject): + def method_append(self, s_str): + assert isinstance(s_str, (SomeUnicodeCodePoint, SomeUnicodeString)) + return s_None + + def method_append_slice(self, s_str, s_start, s_end): + assert isinstance(s_str, SomeUnicodeString) + assert isinstance(s_start, SomeInteger) + assert isinstance(s_end, SomeInteger) + assert s_start.nonneg + assert s_end.nonneg + return s_None + + def method_append_multiple_char(self, s_char, s_times): + assert isinstance(s_char, SomeUnicodeCodePoint) + assert isinstance(s_times, SomeInteger) + assert s_times.nonneg + return s_None + + def method_build(self): + return SomeUnicodeString() + + def rtyper_makerepr(self, rtyper): + return rtyper.type_system.rbuilder.unicodebuilder_repr + class BaseEntry(object): def compute_result_annotation(self, s_init_size=None): - from pypy.rpython.rbuilder import SomeStringBuilder, SomeUnicodeBuilder if s_init_size is not None: - assert s_init_size.is_constant() - init_size = s_init_size.const - else: - init_size = INIT_SIZE + assert isinstance(s_init_size, SomeInteger) if self.use_unicode: - return SomeUnicodeBuilder(init_size) - return SomeStringBuilder(init_size) + return SomeUnicodeBuilder() + return SomeStringBuilder() def specialize_call(self, hop): return hop.r_result.rtyper_new(hop) Modified: pypy/dist/pypy/rlib/test/test_objectmodel.py ============================================================================== --- pypy/dist/pypy/rlib/test/test_objectmodel.py (original) +++ pypy/dist/pypy/rlib/test/test_objectmodel.py Mon May 26 19:08:10 2008 @@ -317,32 +317,3 @@ if option.view: graph.show() return graph - -def test_newlist(): - from pypy.annotation.model import SomeInteger - def f(z): - x = newlist(sizehint=38) - if z < 0: - x.append(1) - return len(x) - - graph = getgraph(f, [SomeInteger()]) - for llop in graph.startblock.operations: - if llop.opname == 'malloc_varsize': - break - assert llop.args[2].value == 38 - -def test_newlist_nonconst(): - from pypy.annotation.model import SomeInteger - from pypy.objspace.flow.model import Variable - def f(z): - x = newlist(sizehint=z) - return len(x) - - graph = getgraph(f, [SomeInteger()]) - for llop in graph.startblock.operations: - if llop.opname == 'malloc_varsize': - break - assert llop.args[2] is graph.startblock.inputargs[0] - - Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Mon May 26 19:08:10 2008 @@ -770,7 +770,8 @@ def op_gc__enable_finalizers(self): self.heap.enable_finalizers() - def op_gc_can_move(self, addr): + def op_gc_can_move(self, ptr): + addr = llmemory.cast_ptr_to_adr(ptr) return self.heap.can_move(addr) def op_gc_free(self, addr): @@ -858,6 +859,14 @@ assert lltype.typeOf(size) == lltype.Signed return llmemory.raw_malloc(size) + def op_raw_realloc_grow(self, addr, old_size, size): + assert lltype.typeOf(size) == lltype.Signed + return llmemory.raw_realloc_grow(addr, old_size, size) + + def op_raw_realloc_shrink(self, addr, old_size, size): + assert lltype.typeOf(size) == lltype.Signed + return llmemory.raw_realloc_shrink(addr, old_size, size) + op_boehm_malloc = op_boehm_malloc_atomic = op_raw_malloc def op_boehm_register_finalizer(self, p, finalizer): Modified: pypy/dist/pypy/rpython/lltypesystem/llmemory.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/llmemory.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/llmemory.py Mon May 26 19:08:10 2008 @@ -693,6 +693,18 @@ raise NotImplementedError(size) return size._raw_malloc([], zero=False) +def raw_realloc_grow(addr, old_size, size): + new_area = size._raw_malloc([], zero=False) + raw_memcopy(addr, new_area, old_size) + raw_free(addr) + return new_area + +def raw_realloc_shrink(addr, old_size, size): + new_area = size._raw_malloc([], zero=False) + raw_memcopy(addr, new_area, size) + raw_free(addr) + return new_area + def raw_free(adr): # try to free the whole object if 'adr' is the address of the header from pypy.rpython.memory.gcheader import GCHeaderBuilder @@ -747,9 +759,11 @@ T = lltype.typeOf(source).TO assert T == lltype.typeOf(dest).TO if isinstance(T, (lltype.Array, lltype.FixedSizeArray)): - assert source._obj.getlength() == dest._obj.getlength() + sourcelgt = source._obj.getlength() + destlgt = dest._obj.getlength() + lgt = min(sourcelgt, destlgt) ITEMTYPE = T.OF - for i in range(source._obj.getlength()): + for i in range(lgt): if isinstance(ITEMTYPE, lltype.ContainerType): subsrc = source._obj.getitem(i)._as_ptr() subdst = dest._obj.getitem(i)._as_ptr() Modified: pypy/dist/pypy/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/lloperation.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/lloperation.py Mon May 26 19:08:10 2008 @@ -326,8 +326,8 @@ 'malloc_nonmovable': LLOp(canraise=(MemoryError,), canunwindgc=True), 'malloc_nonmovable_varsize':LLOp(canraise=(MemoryError,),canunwindgc=True), 'malloc_resizable_buffer': LLOp(canraise=(MemoryError,),canunwindgc=True), - 'resize_buffer': LLOp(canraise=(MemoryError,),canunwindgc=True), - 'finish_building_buffer' : LLOp(), + 'resize_buffer': LLOp(canraise=(MemoryError,), canunwindgc=True), + 'finish_building_buffer' : LLOp(canraise=(MemoryError,), canunwindgc=True), 'zero_gc_pointers_inside': LLOp(), 'free': LLOp(), 'getfield': LLOp(sideeffects=False, canrun=True), @@ -362,6 +362,8 @@ 'boehm_register_finalizer': LLOp(), 'boehm_disappearing_link': LLOp(), 'raw_malloc': LLOp(), + 'raw_realloc_grow': LLOp(), + 'raw_realloc_shrink': LLOp(), 'raw_malloc_usage': LLOp(sideeffects=False), 'raw_free': LLOp(), 'raw_memclear': LLOp(), Modified: pypy/dist/pypy/rpython/lltypesystem/rbuilder.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rbuilder.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rbuilder.py Mon May 26 19:08:10 2008 @@ -1,16 +1,31 @@ from pypy.rpython.rbuilder import AbstractStringBuilderRepr from pypy.rpython.lltypesystem import lltype -from pypy.rpython.lltypesystem.rstr import STR, UNICODE +from pypy.rpython.lltypesystem.rstr import STR, UNICODE, char_repr,\ + string_repr, unichar_repr, unicode_repr from pypy.rpython.annlowlevel import llstr from pypy.rlib import rgc +from pypy.rlib.rarithmetic import ovfcheck from pypy.rpython.lltypesystem.lltype import staticAdtMethod from pypy.tool.sourcetools import func_with_new_name +GROW_FAST_UNTIL = 100*1024*1024 # 100 MB + def new_grow_func(name): def stringbuilder_grow(ll_builder, needed): - # XXX tweak overallocation scheme - new_allocated = ll_builder.allocated + needed + 100 + allocated = ll_builder.allocated + if allocated < GROW_FAST_UNTIL: + new_allocated = allocated << 1 + else: + extra_size = allocated >> 2 + try: + new_allocated = ovfcheck(allocated + extra_size) + except OverflowError: + raise MemoryError + try: + new_allocated = ovfcheck(new_allocated + needed) + except OverflowError: + raise MemoryError ll_builder.buf = rgc.resize_buffer(ll_builder.buf, ll_builder.used, new_allocated) ll_builder.allocated = new_allocated @@ -31,9 +46,13 @@ ('buf', lltype.Ptr(UNICODE)), adtmeths={'grow':staticAdtMethod(unicodebuilder_grow)}) +MAX = 16*1024*1024 + class BaseStringBuilderRepr(AbstractStringBuilderRepr): @classmethod def ll_new(cls, init_size): + if init_size < 0 or init_size > MAX: + init_size = MAX ll_builder = lltype.malloc(cls.lowleveltype.TO) ll_builder.allocated = init_size ll_builder.used = 0 @@ -85,10 +104,14 @@ class StringBuilderRepr(BaseStringBuilderRepr): lowleveltype = lltype.Ptr(STRINGBUILDER) basetp = STR + string_repr = string_repr + char_repr = char_repr class UnicodeBuilderRepr(BaseStringBuilderRepr): lowleveltype = lltype.Ptr(UNICODEBUILDER) basetp = UNICODE + string_repr = unicode_repr + char_repr = unichar_repr unicodebuilder_repr = UnicodeBuilderRepr() stringbuilder_repr = StringBuilderRepr() Modified: pypy/dist/pypy/rpython/lltypesystem/rlist.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rlist.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rlist.py Mon May 26 19:08:10 2008 @@ -71,7 +71,6 @@ ITEMARRAY = GcArray(ITEM, adtmeths = ADTIFixedList({ "ll_newlist": ll_fixed_newlist, - "ll_newlist_hint": ll_fixed_newlist, "ll_newemptylist": ll_fixed_newemptylist, "ll_length": ll_fixed_length, "ll_items": ll_fixed_items, @@ -105,7 +104,6 @@ ("items", Ptr(ITEMARRAY)), adtmeths = ADTIList({ "ll_newlist": ll_newlist, - "ll_newlist_hint": ll_newlist_hint, "ll_newemptylist": ll_newemptylist, "ll_length": ll_length, "ll_items": ll_items, @@ -290,15 +288,6 @@ ll_newlist = typeMethod(ll_newlist) ll_newlist.oopspec = 'newlist(length)' -def ll_newlist_hint(LIST, lengthhint): - ll_assert(lengthhint >= 0, "negative list length") - l = malloc(LIST) - l.length = 0 - l.items = malloc(LIST.items.TO, lengthhint) - return l -ll_newlist_hint = typeMethod(ll_newlist_hint) -ll_newlist_hint.oopspec = 'newlist(length)' - # should empty lists start with no allocated memory, or with a preallocated # minimal number of entries? XXX compare memory usage versus speed, and # check how many always-empty lists there are in a typical pypy-c run... @@ -360,13 +349,10 @@ ll_assert(index < len(l), "fixed setitem out of bounds") l[index] = item -def newlist(llops, r_list, items_v, v_sizehint=None): +def newlist(llops, r_list, items_v): LIST = r_list.LIST if len(items_v) == 0: - if v_sizehint is None: - v_result = llops.gendirectcall(LIST.ll_newemptylist) - else: - v_result = llops.gendirectcall(LIST.ll_newlist_hint, v_sizehint) + v_result = llops.gendirectcall(LIST.ll_newemptylist) else: cno = inputconst(Signed, len(items_v)) v_result = llops.gendirectcall(LIST.ll_newlist, cno) Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py Mon May 26 19:08:10 2008 @@ -612,3 +612,31 @@ # 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_realloc(): + A = lltype.Array(lltype.Float) + adr = raw_malloc(sizeof(A, 10)) + ptr = cast_adr_to_ptr(adr, lltype.Ptr(A)) + for i in range(10): + ptr[i] = float(i) + adr2 = raw_realloc_shrink(adr, sizeof(A, 10), sizeof(A, 5)) + ptr2 = cast_adr_to_ptr(adr2, lltype.Ptr(A)) + assert len(ptr2) == 5 + assert ptr2[3] == 3.0 + assert ptr2[1] == 1.0 + +def test_realloc_struct(): + S = lltype.Struct('x', ('one', lltype.Signed), + ('a', lltype.Array(lltype.Float))) + adr = raw_malloc(sizeof(S, 5)) + ptr = cast_adr_to_ptr(adr, lltype.Ptr(S)) + for i in range(5): + ptr.a[i] = float(i) + ptr.one = 3 + adr2 = raw_realloc_grow(adr, sizeof(S, 5), sizeof(S, 10)) + ptr2 = cast_adr_to_ptr(adr2, lltype.Ptr(S)) + assert len(ptr2.a) == 10 + assert ptr2.a[3] == 3.0 + assert ptr2.a[0] == 0.0 + assert ptr2.one == 3 + Modified: pypy/dist/pypy/rpython/memory/gc/base.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gc/base.py (original) +++ pypy/dist/pypy/rpython/memory/gc/base.py Mon May 26 19:08:10 2008 @@ -9,6 +9,9 @@ prebuilt_gc_objects_are_static_roots = True can_realloc = False + def can_malloc_nonmovable(self): + return not self.moving_gc + # The following flag enables costly consistency checks after each # collection. It is automatically set to True by test_gc.py. The # checking logic is translatable, so the flag can be set to True @@ -39,7 +42,7 @@ def set_root_walker(self, root_walker): self.root_walker = root_walker - def write_barrier(self, oldvalue, newvalue, addr_struct): + def write_barrier(self, newvalue, addr_struct): pass def setup(self): @@ -85,6 +88,9 @@ # lots of cast and reverse-cast around... return llmemory.cast_ptr_to_adr(ref) + def malloc_nonmovable(self, typeid, length=0, zero=False): + return self.malloc(typeid, length, zero) + def id(self, ptr): return lltype.cast_ptr_to_int(ptr) Modified: pypy/dist/pypy/rpython/memory/gc/generation.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gc/generation.py (original) +++ pypy/dist/pypy/rpython/memory/gc/generation.py Mon May 26 19:08:10 2008 @@ -407,7 +407,7 @@ continue # no need to remember this weakref any longer self.objects_with_weakrefs.append(obj) - def write_barrier(self, oldvalue, newvalue, addr_struct): + def write_barrier(self, newvalue, addr_struct): if self.header(addr_struct).tid & GCFLAG_NO_YOUNG_PTRS: self.remember_young_pointer(addr_struct, newvalue) Modified: pypy/dist/pypy/rpython/memory/gc/hybrid.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gc/hybrid.py (original) +++ pypy/dist/pypy/rpython/memory/gc/hybrid.py Mon May 26 19:08:10 2008 @@ -10,6 +10,7 @@ from pypy.rpython.lltypesystem.lloperation import llop from pypy.rlib.debug import ll_assert from pypy.rlib.rarithmetic import ovfcheck +from pypy.rpython.lltypesystem import rffi # _______in the semispaces_________ ______external (non-moving)_____ # / \ / \ @@ -29,6 +30,7 @@ # Object lists: # * gen2_rawmalloced_objects # * gen3_rawmalloced_objects +# * gen2_resizable_objects # * old_objects_pointing_to_young: gen2or3 objs that point to gen1 objs # * last_generation_root_objects: gen3 objs that point to gen1or2 objs # @@ -41,11 +43,15 @@ # Some invariants: # * gen3 are either GCFLAG_NO_HEAP_PTRS or in 'last_generation_root_objects' # * between collections, GCFLAG_UNVISITED set exactly for gen2_rawmalloced +# * objects in gen2_resizable_objects are part of the generation 2 but never +# explicitly listed in gen2_rawmalloced_objects. # # A malloc_varsize() of large objects returns objects that are external # but initially of generation 2. Old objects from the semispaces are # moved to external objects directly as generation 3. +# gen2_resizable_objects is for objects that are resizable + # The "age" of an object is the number of times it survived a full # collections, without counting the step that moved it out of the nursery. # When a semispace-based object would grow older than MAX_SEMISPACE_AGE, @@ -68,7 +74,6 @@ # number of calls to semispace_collect(): GENERATION3_COLLECT_THRESHOLD = 20 - class HybridGC(GenerationGC): """A two-generations semi-space GC like the GenerationGC, except that objects above a certain size are handled separately: @@ -76,6 +81,7 @@ """ first_unused_gcflag = _gcflag_next_bit prebuilt_gc_objects_are_static_roots = True + can_realloc = True # the following values override the default arguments of __init__ when # translating to a real backend. @@ -117,6 +123,7 @@ def setup(self): self.gen2_rawmalloced_objects = self.AddressStack() self.gen3_rawmalloced_objects = self.AddressStack() + self.gen2_resizable_objects = self.AddressStack() GenerationGC.setup(self) def set_max_heap_size(self, size): @@ -169,7 +176,8 @@ llmemory.GCREF) return self.malloc_varsize_slowpath(typeid, length) - def malloc_varsize_slowpath(self, typeid, length): + def malloc_varsize_slowpath(self, typeid, length, force_nonmovable=False, + resizable=False): # For objects that are too large, or when the nursery is exhausted. # In order to keep malloc_varsize_clear() as compact as possible, # we recompute what we need in this slow path instead of passing @@ -187,8 +195,8 @@ nonlarge_max = self.nonlarge_gcptrs_max else: nonlarge_max = self.nonlarge_max - if raw_malloc_usage(totalsize) > nonlarge_max: - result = self.malloc_varsize_marknsweep(totalsize) + if force_nonmovable or raw_malloc_usage(totalsize) > nonlarge_max: + result = self.malloc_varsize_marknsweep(totalsize, resizable) flags = self.GCFLAGS_FOR_NEW_EXTERNAL_OBJECTS | GCFLAG_UNVISITED else: result = self.malloc_varsize_collecting_nursery(totalsize) @@ -199,6 +207,57 @@ malloc_varsize_slowpath._dont_inline_ = True + def malloc_varsize_nonmovable(self, typeid, length): + return self.malloc_varsize_slowpath(typeid, length, True) + + def malloc_varsize_resizable(self, typeid, length): + return self.malloc_varsize_slowpath(typeid, length, True, True) + + def malloc_nonmovable(self, typeid, length, zero): + # helper for testing, same as GCBase.malloc + if self.is_varsize(typeid): + gcref = self.malloc_varsize_slowpath(typeid, length, True) + else: + raise NotImplementedError("Not supported") + return llmemory.cast_ptr_to_adr(gcref) + + def realloc(self, ptr, newlength, fixedsize, itemsize, lengthofs, grow): + size_gc_header = self.size_gc_header() + addr = llmemory.cast_ptr_to_adr(ptr) + tid = self.get_type_id(addr) + nonvarsize = size_gc_header + fixedsize + try: + varsize = ovfcheck(itemsize * newlength) + tot_size = ovfcheck(nonvarsize + varsize) + except OverflowError: + raise MemoryError() + oldlength = (addr + lengthofs).signed[0] + old_tot_size = size_gc_header + fixedsize + oldlength * itemsize + source_addr = addr - size_gc_header + self.gen2_resizable_objects.remove(addr) + if grow: + result = llop.raw_realloc_grow(llmemory.Address, source_addr, + old_tot_size, tot_size) + else: + result = llop.raw_realloc_shrink(llmemory.Address, source_addr, + old_tot_size, tot_size) + if not result: + self.gen2_resizable_objects.append(addr) + raise MemoryError() + if grow: + self.gen2_resizable_objects.append(result + size_gc_header) + else: + self.gen2_rawmalloced_objects.append(result + size_gc_header) + self._check_rawsize_alloced(raw_malloc_usage(tot_size) - + raw_malloc_usage(old_tot_size), + can_collect = not grow) + (result + size_gc_header + lengthofs).signed[0] = newlength + return llmemory.cast_adr_to_ptr(result + size_gc_header, llmemory.GCREF) + + def can_move(self, addr): + tid = self.header(addr).tid + return not (tid & GCFLAG_EXTERNAL) + def malloc_varsize_collecting_nursery(self, totalsize): result = self.collect_nursery() ll_assert(raw_malloc_usage(totalsize) <= self.nursery_top - result, @@ -208,7 +267,17 @@ totalsize) return result - def malloc_varsize_marknsweep(self, totalsize): + def _check_rawsize_alloced(self, size_estimate, can_collect=True): + self.large_objects_collect_trigger -= size_estimate + if can_collect and self.large_objects_collect_trigger < 0: + if DEBUG_PRINT: + llop.debug_print(lltype.Void, "allocated", + self._initial_trigger - + self.large_objects_collect_trigger, + "bytes, triggering full collection") + self.semispace_collect() + + def malloc_varsize_marknsweep(self, totalsize, resizable=False): # In order to free the large objects from time to time, we # arbitrarily force a full collect() if none occurs when we have # allocated 'self.space_size' bytes of large objects. @@ -216,14 +285,7 @@ # XXX and adjust sizes based on it; otherwise we risk doing # XXX many many collections if the program allocates a lot # XXX more than the current self.space_size. - self.large_objects_collect_trigger -= raw_malloc_usage(totalsize) - if self.large_objects_collect_trigger < 0: - if DEBUG_PRINT: - llop.debug_print(lltype.Void, "allocated", - self._initial_trigger - - self.large_objects_collect_trigger, - "bytes, triggering full collection") - self.semispace_collect() + self._check_rawsize_alloced(raw_malloc_usage(totalsize)) result = self.allocate_external_object(totalsize) if not result: raise MemoryError() @@ -231,7 +293,10 @@ # need to follow suit. llmemory.raw_memclear(result, totalsize) size_gc_header = self.gcheaderbuilder.size_gc_header - self.gen2_rawmalloced_objects.append(result + size_gc_header) + if resizable: + self.gen2_resizable_objects.append(result + size_gc_header) + else: + self.gen2_rawmalloced_objects.append(result + size_gc_header) return result def allocate_external_object(self, totalsize): @@ -394,6 +459,7 @@ if self.is_collecting_gen3(): self.sweep_rawmalloced_objects(generation=3) self.sweep_rawmalloced_objects(generation=2) + self.sweep_rawmalloced_objects(generation=-2) # As we just collected, it's fine to raw_malloc'ate up to space_size # bytes again before we should force another collect. self.large_objects_collect_trigger = self.space_size @@ -412,7 +478,7 @@ # to any gen2 object. In this case, A remains a bit too long in # last_generation_root_objects, but this will be fixed by the # next collect_last_generation_roots(). - else: + elif generation == 3: objects = self.gen3_rawmalloced_objects # generation 3 sweep: remove from last_generation_root_objects # all the objects that we are about to free @@ -424,6 +490,11 @@ newgen3roots.append(obj) gen3roots.delete() self.last_generation_root_objects = newgen3roots + else: + # mostly a hack: the generation number -2 is the part of the + # generation 2 that lives in gen2_resizable_objects + ll_assert(generation == -2, "bogus 'generation'") + objects = self.gen2_resizable_objects surviving_objects = self.AddressStack() if DEBUG_PRINT: alive_count = alive_size = 0 @@ -441,7 +512,7 @@ if DEBUG_PRINT:alive_size+=raw_malloc_usage(self.get_size(obj)) if generation == 3: surviving_objects.append(obj) - else: + elif generation == 2: ll_assert((tid & GCFLAG_AGE_MASK) < GCFLAG_AGE_MAX, "wrong age for generation 2 object") tid += GCFLAG_AGE_ONE @@ -455,11 +526,18 @@ tid |= GCFLAG_UNVISITED surviving_objects.append(obj) self.header(obj).tid = tid + elif generation == -2: + # the object stays in generation -2 + tid |= GCFLAG_UNVISITED + surviving_objects.append(obj) + self.header(obj).tid = tid objects.delete() if generation == 2: self.gen2_rawmalloced_objects = surviving_objects - else: + elif generation == 3: self.gen3_rawmalloced_objects = surviving_objects + elif generation == -2: + self.gen2_resizable_objects = surviving_objects if DEBUG_PRINT: llop.debug_print(lltype.Void, "| [hyb] gen", generation, @@ -521,3 +599,6 @@ "gen3: unexpected GCFLAG_UNVISITED") ll_assert((tid & GCFLAG_AGE_MASK) == GCFLAG_AGE_MAX, "gen3: wrong age field") + + def can_malloc_nonmovable(self): + return True Modified: pypy/dist/pypy/rpython/memory/gc/test/test_direct.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gc/test/test_direct.py (original) +++ pypy/dist/pypy/rpython/memory/gc/test/test_direct.py Mon May 26 19:08:10 2008 @@ -78,18 +78,16 @@ def write(self, p, fieldname, newvalue): if self.gc.needs_write_barrier: - oldaddr = llmemory.cast_ptr_to_adr(getattr(p, fieldname)) newaddr = llmemory.cast_ptr_to_adr(newvalue) addr_struct = llmemory.cast_ptr_to_adr(p) - self.gc.write_barrier(oldaddr, newaddr, addr_struct) + self.gc.write_barrier(newaddr, addr_struct) setattr(p, fieldname, newvalue) def writearray(self, p, index, newvalue): if self.gc.needs_write_barrier: - oldaddr = llmemory.cast_ptr_to_adr(p[index]) newaddr = llmemory.cast_ptr_to_adr(newvalue) addr_struct = llmemory.cast_ptr_to_adr(p) - self.gc.write_barrier(oldaddr, newaddr, addr_struct) + self.gc.write_barrier(newaddr, addr_struct) p[index] = newvalue def malloc(self, TYPE, n=None): Modified: pypy/dist/pypy/rpython/memory/gctransform/boehm.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gctransform/boehm.py (original) +++ pypy/dist/pypy/rpython/memory/gctransform/boehm.py Mon May 26 19:08:10 2008 @@ -64,7 +64,7 @@ return True def perform_realloc(self, hop, v_ptr, v_newlgt, c_const_size, c_item_size, - c_lengthofs): + c_lengthofs, c_grow): args = [self.realloc_ptr, v_ptr, v_newlgt, c_const_size, c_item_size, c_lengthofs] return hop.genop('direct_call', args, resulttype=llmemory.Address) Modified: pypy/dist/pypy/rpython/memory/gctransform/framework.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gctransform/framework.py (original) +++ pypy/dist/pypy/rpython/memory/gctransform/framework.py Mon May 26 19:08:10 2008 @@ -273,6 +273,36 @@ else: self.malloc_varsize_clear_fast_ptr = None + if getattr(GCClass, 'malloc_varsize_nonmovable', False): + malloc_nonmovable = func_with_new_name( + GCClass.malloc_varsize_nonmovable.im_func, + "malloc_varsize_nonmovable") + self.malloc_varsize_nonmovable_ptr = getfn( + malloc_nonmovable, + [s_gc, annmodel.SomeInteger(nonneg=True), + annmodel.SomeInteger(nonneg=True)], s_gcref) + else: + self.malloc_varsize_nonmovable_ptr = None + + if getattr(GCClass, 'malloc_varsize_resizable', False): + malloc_resizable = func_with_new_name( + GCClass.malloc_varsize_resizable.im_func, + "malloc_varsize_resizable") + self.malloc_varsize_resizable_ptr = getfn( + malloc_resizable, + [s_gc, annmodel.SomeInteger(nonneg=True), + annmodel.SomeInteger(nonneg=True)], s_gcref) + else: + self.malloc_varsize_resizable_ptr = None + + if getattr(GCClass, 'realloc', False): + self.realloc_ptr = getfn( + GCClass.realloc.im_func, + [s_gc, s_gcref] + + [annmodel.SomeInteger(nonneg=True)] * 4 + + [annmodel.SomeBool()], + s_gcref) + if GCClass.moving_gc: self.id_ptr = getfn(GCClass.id.im_func, [s_gc, s_gcref], annmodel.SomeInteger(), @@ -288,7 +318,7 @@ if GCClass.needs_write_barrier: self.write_barrier_ptr = getfn(GCClass.write_barrier.im_func, - [s_gc, annmodel.SomeAddress(), + [s_gc, annmodel.SomeAddress(), annmodel.SomeAddress()], annmodel.s_None, @@ -456,15 +486,29 @@ v_length = op.args[-1] c_ofstolength = rmodel.inputconst(lltype.Signed, info.ofstolength) c_varitemsize = rmodel.inputconst(lltype.Signed, info.varitemsize) - if (self.malloc_varsize_clear_fast_ptr is not None and - c_can_collect.value and not c_has_finalizer.value): - malloc_ptr = self.malloc_varsize_clear_fast_ptr + if flags.get('resizable') and self.malloc_varsize_resizable_ptr: + assert c_can_collect.value + assert not c_has_finalizer.value + malloc_ptr = self.malloc_varsize_resizable_ptr + args = [self.c_const_gc, c_type_id, v_length] + elif flags.get('nonmovable') and self.malloc_varsize_nonmovable_ptr: + # we don't have tests for such cases, let's fail + # explicitely + assert c_can_collect.value + assert not c_has_finalizer.value + malloc_ptr = self.malloc_varsize_nonmovable_ptr + args = [self.c_const_gc, c_type_id, v_length] else: - malloc_ptr = self.malloc_varsize_clear_ptr - args = [self.c_const_gc, c_type_id, v_length, c_size, - c_varitemsize, c_ofstolength, c_can_collect, - c_has_finalizer] - livevars = self.push_roots(hop) + if (self.malloc_varsize_clear_fast_ptr is not None and + c_can_collect.value and not c_has_finalizer.value): + malloc_ptr = self.malloc_varsize_clear_fast_ptr + else: + malloc_ptr = self.malloc_varsize_clear_ptr + args = [self.c_const_gc, c_type_id, v_length, c_size, + c_varitemsize, c_ofstolength, c_can_collect, + c_has_finalizer] + keep_current_args = flags.get('keep_current_args', False) + livevars = self.push_roots(hop, keep_current_args=keep_current_args) v_result = hop.genop("direct_call", [malloc_ptr] + args, resulttype=llmemory.GCREF) self.pop_roots(hop, livevars) @@ -489,6 +533,16 @@ def _can_realloc(self): return self.gcdata.gc.can_realloc + def perform_realloc(self, hop, v_ptr, v_newsize, c_const_size, + c_itemsize, c_lengthofs, c_grow): + vlist = [self.realloc_ptr, self.c_const_gc, v_ptr, v_newsize, + c_const_size, c_itemsize, c_lengthofs, c_grow] + livevars = self.push_roots(hop) + v_result = hop.genop('direct_call', vlist, + resulttype=llmemory.GCREF) + self.pop_roots(hop, livevars) + return v_result + def gct_gc__disable_finalizers(self, hop): # cannot collect() op = hop.spaceop @@ -593,19 +647,17 @@ def gct_malloc_nonmovable_varsize(self, hop): TYPE = hop.spaceop.result.concretetype - if self.gcdata.gc.moving_gc: - # first approximation - c = rmodel.inputconst(TYPE, lltype.nullptr(TYPE.TO)) - return hop.cast_result(c) - return self.gct_malloc_varsize(hop) + if self.gcdata.gc.can_malloc_nonmovable(): + return self.gct_malloc_varsize(hop, {'nonmovable':True}) + c = rmodel.inputconst(TYPE, lltype.nullptr(TYPE.TO)) + return hop.cast_result(c) def gct_malloc_nonmovable(self, hop): TYPE = hop.spaceop.result.concretetype - if self.gcdata.gc.moving_gc: - # first approximation - c = rmodel.inputconst(TYPE, lltype.nullptr(TYPE.TO)) - return hop.cast_result(c) - return self.gct_malloc(hop) + if self.gcdata.gc.can_malloc_nonmovable(): + return self.gct_malloc(hop, {'nonmovable':True}) + c = rmodel.inputconst(TYPE, lltype.nullptr(TYPE.TO)) + return hop.cast_result(c) def transform_generic_set(self, hop): from pypy.objspace.flow.model import Constant @@ -621,18 +673,12 @@ and v_struct.concretetype.TO._gckind == "gc" and hop.spaceop not in self.initializing_stores): self.write_barrier_calls += 1 - v_oldvalue = hop.genop('g' + opname[1:], - hop.inputargs()[:-1], - resulttype=v_newvalue.concretetype) - v_oldvalue = hop.genop("cast_ptr_to_adr", [v_oldvalue], - resulttype = llmemory.Address) v_newvalue = hop.genop("cast_ptr_to_adr", [v_newvalue], resulttype = llmemory.Address) v_structaddr = hop.genop("cast_ptr_to_adr", [v_struct], resulttype = llmemory.Address) hop.genop("direct_call", [self.write_barrier_ptr, self.c_const_gc, - v_oldvalue, v_newvalue, v_structaddr]) hop.rename('bare_' + opname) Modified: pypy/dist/pypy/rpython/memory/gctransform/transform.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gctransform/transform.py (original) +++ pypy/dist/pypy/rpython/memory/gctransform/transform.py Mon May 26 19:08:10 2008 @@ -495,7 +495,7 @@ self.stack_malloc_fixedsize_ptr = self.inittime_helper( ll_stack_malloc_fixedsize, [lltype.Signed], llmemory.Address) - def gct_malloc(self, hop): + def gct_malloc(self, hop, add_flags=None): TYPE = hop.spaceop.result.concretetype.TO assert not TYPE._is_varsize() flags = hop.spaceop.args[1].value @@ -520,21 +520,27 @@ hop.genop("raw_memclear", [v_raw, c_size]) return v_raw - def gct_malloc_varsize(self, hop): - + def gct_malloc_varsize(self, hop, add_flags=None): flags = hop.spaceop.args[1].value + if add_flags: + flags.update(add_flags) flavor = flags['flavor'] assert flavor != 'cpy', "cannot malloc CPython objects directly" meth = getattr(self, 'gct_fv_%s_malloc_varsize' % flavor, None) assert meth, "%s has no support for malloc_varsize with flavor %r" % (self, flavor) return self.varsize_malloc_helper(hop, flags, meth, []) - gct_malloc_nonmovable = gct_malloc - gct_malloc_nonmovable_varsize = gct_malloc_varsize + def gct_malloc_nonmovable(self, *args, **kwds): + return self.gct_malloc(*args, **kwds) + + def gct_malloc_nonmovable_varsize(self, *args, **kwds): + return self.gct_malloc_varsize(*args, **kwds) def gct_malloc_resizable_buffer(self, hop): flags = hop.spaceop.args[1].value flags['varsize'] = True + flags['nonmovable'] = True + flags['resizable'] = True flavor = flags['flavor'] assert flavor != 'cpy', "cannot malloc CPython objects directly" meth = getattr(self, 'gct_fv_%s_malloc_varsize' % flavor, None) @@ -544,14 +550,14 @@ def gct_resize_buffer(self, hop): op = hop.spaceop if self._can_realloc(): - self._gct_resize_buffer_realloc(hop, op.args[2]) + self._gct_resize_buffer_realloc(hop, op.args[2], True) else: self._gct_resize_buffer_no_realloc(hop, op.args[1]) def _can_realloc(self): return False - def _gct_resize_buffer_realloc(self, hop, v_newsize): + def _gct_resize_buffer_realloc(self, hop, v_newsize, grow=True): def intconst(c): return rmodel.inputconst(lltype.Signed, c) op = hop.spaceop flags = {'flavor':'gc', 'varsize': True} @@ -564,14 +570,16 @@ c_lengthofs = intconst(offset_to_length) v_ptr = op.args[0] + v_ptr = gen_cast(hop.llops, llmemory.GCREF, v_ptr) + c_grow = rmodel.inputconst(lltype.Bool, grow) v_raw = self.perform_realloc(hop, v_ptr, v_newsize, c_const_size, - c_item_size, c_lengthofs) + c_item_size, c_lengthofs, c_grow) hop.cast_result(v_raw) def _gct_resize_buffer_no_realloc(self, hop, v_lgt): op = hop.spaceop meth = self.gct_fv_gc_malloc_varsize - flags = {'flavor':'gc', 'varsize': True} + flags = {'flavor':'gc', 'varsize': True, 'keep_current_args': True} self.varsize_malloc_helper(hop, flags, meth, []) # fish resvar v_newbuf = hop.llops[-1].result @@ -599,7 +607,7 @@ def gct_finish_building_buffer(self, hop): op = hop.spaceop if self._can_realloc(): - return self._gct_resize_buffer_realloc(hop, op.args[1]) + return self._gct_resize_buffer_realloc(hop, op.args[1], False) else: return self._gct_resize_buffer_no_realloc(hop, op.args[1]) Modified: pypy/dist/pypy/rpython/memory/gcwrapper.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gcwrapper.py (original) +++ pypy/dist/pypy/rpython/memory/gcwrapper.py Mon May 26 19:08:10 2008 @@ -46,9 +46,9 @@ def malloc_nonmovable(self, TYPE, n=None, zero=False): typeid = self.get_type_id(TYPE) - if self.gc.moving_gc: + if not self.gc.can_malloc_nonmovable(): return lltype.nullptr(TYPE) - addr = self.gc.malloc(typeid, n, zero=zero) + addr = self.gc.malloc_nonmovable(typeid, n, zero=zero) result = llmemory.cast_adr_to_ptr(addr, lltype.Ptr(TYPE)) if not self.gc.malloc_zero_filled: gctypelayout.zero_gc_pointers(result) @@ -95,9 +95,7 @@ def setinterior(self, toplevelcontainer, inneraddr, INNERTYPE, newvalue): if (lltype.typeOf(toplevelcontainer).TO._gckind == 'gc' and isinstance(INNERTYPE, lltype.Ptr) and INNERTYPE.TO._gckind == 'gc'): - oldvalue = inneraddr.address[0] - self.gc.write_barrier(oldvalue, - llmemory.cast_ptr_to_adr(newvalue), + self.gc.write_barrier(llmemory.cast_ptr_to_adr(newvalue), llmemory.cast_ptr_to_adr(toplevelcontainer)) llheap.setinterior(toplevelcontainer, inneraddr, INNERTYPE, newvalue) Modified: pypy/dist/pypy/rpython/memory/support.py ============================================================================== --- pypy/dist/pypy/rpython/memory/support.py (original) +++ pypy/dist/pypy/rpython/memory/support.py Mon May 26 19:08:10 2008 @@ -138,6 +138,22 @@ self.foreach(_add_in_dict, result) return result + def remove(self, addr): + """Remove 'addr' from the stack. The addr *must* be in the list, + and preferrably near the top. + """ + got = self.pop() + chunk = self.chunk + count = self.used_in_last_chunk + while got != addr: + count -= 1 + if count < 0: + chunk = chunk.next + count = chunk_size - 1 + next = chunk.items[count] + chunk.items[count] = got + got = next + cache[chunk_size] = AddressStack return AddressStack Modified: pypy/dist/pypy/rpython/memory/test/test_gc.py ============================================================================== --- pypy/dist/pypy/rpython/memory/test/test_gc.py (original) +++ pypy/dist/pypy/rpython/memory/test/test_gc.py Mon May 26 19:08:10 2008 @@ -22,6 +22,7 @@ class GCTest(object): GC_PARAMS = {} GC_CAN_MOVE = False + GC_CANNOT_MALLOC_NONMOVABLE = False def setup_class(cls): cls._saved_logstate = py.log._getstate() @@ -400,17 +401,14 @@ def test_malloc_nonmovable(self): TP = lltype.GcArray(lltype.Char) def func(): - try: - from pypy.rlib import rgc - a = rgc.malloc_nonmovable(TP, 3) - if a: - assert not rgc.can_move(a) - return 0 - return 1 - except Exception, e: - return 2 + from pypy.rlib import rgc + a = rgc.malloc_nonmovable(TP, 3) + if a: + assert not rgc.can_move(a) + return 0 + return 1 - assert self.interpret(func, []) == int(self.GC_CAN_MOVE) + assert self.interpret(func, []) == int(self.GC_CANNOT_MALLOC_NONMOVABLE) def test_malloc_nonmovable_fixsize(self): S = lltype.GcStruct('S', ('x', lltype.Float)) @@ -427,7 +425,7 @@ except Exception, e: return 2 - assert self.interpret(func, []) == int(self.GC_CAN_MOVE) + assert self.interpret(func, []) == int(self.GC_CANNOT_MALLOC_NONMOVABLE) def test_resizable_buffer(self): from pypy.rpython.lltypesystem.rstr import STR @@ -449,6 +447,7 @@ class TestSemiSpaceGC(GCTest, snippet.SemiSpaceGCTests): from pypy.rpython.memory.gc.semispace import SemiSpaceGC as GCClass GC_CAN_MOVE = True + GC_CANNOT_MALLOC_NONMOVABLE = True class TestGrowingSemiSpaceGC(TestSemiSpaceGC): GC_PARAMS = {'space_size': 64} @@ -458,6 +457,7 @@ class TestHybridGC(TestGenerationalGC): from pypy.rpython.memory.gc.hybrid import HybridGC as GCClass + GC_CANNOT_MALLOC_NONMOVABLE = False def test_ref_from_rawmalloced_to_regular(self): import gc @@ -520,8 +520,14 @@ res = self.interpret(f, [15]) assert res == 16 + def test_malloc_nonmovable_fixsize(self): + py.test.skip("Not supported") + class TestHybridGCSmallHeap(GCTest): from pypy.rpython.memory.gc.hybrid import HybridGC as GCClass + GC_CAN_MOVE = False # with this size of heap, stuff gets allocated + # in 3rd gen. + GC_CANNOT_MALLOC_NONMOVABLE = False GC_PARAMS = {'space_size': 192, 'min_nursery_size': 48, 'nursery_size': 48, @@ -562,3 +568,6 @@ return i res = self.interpret(f, [200]) assert res == 401 + + def test_malloc_nonmovable_fixsize(self): + py.test.skip("Not supported") Modified: pypy/dist/pypy/rpython/memory/test/test_support.py ============================================================================== --- pypy/dist/pypy/rpython/memory/test/test_support.py (original) +++ pypy/dist/pypy/rpython/memory/test/test_support.py Mon May 26 19:08:10 2008 @@ -78,6 +78,22 @@ ll.foreach(callback, 42) assert seen == addrs or seen[::-1] == addrs # order not guaranteed + def test_remove(self): + AddressStack = get_address_stack() + addrs = [raw_malloc(llmemory.sizeof(lltype.Signed)) + for i in range(2200)] + ll = AddressStack() + for i in range(2200): + ll.append(addrs[i]) + ll.remove(addrs[-400]) + expected = range(2200) + del expected[-400] + expected.reverse() + for i in expected: + a = ll.pop() + assert a == addrs[i] + assert not ll.non_empty() + class TestAddressDeque: def test_big_access(self): Modified: pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py ============================================================================== --- pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py (original) +++ pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py Mon May 26 19:08:10 2008 @@ -10,6 +10,7 @@ from pypy.rlib.objectmodel import compute_unique_id from pypy.rlib.debug import ll_assert from pypy import conftest +from pypy.rlib.rstring import StringBuilder INT_SIZE = struct.calcsize("i") # only for estimates @@ -37,6 +38,7 @@ gcpolicy = None stacklessgc = False GC_CAN_MOVE = False + GC_CANNOT_MALLOC_NONMOVABLE = False def runner(self, f, nbargs=0, statistics=False, transformer=False, **extraconfigopts): @@ -459,19 +461,19 @@ def test_malloc_nonmovable(self): TP = lltype.GcArray(lltype.Char) def func(): - try: - from pypy.rlib import rgc - a = rgc.malloc_nonmovable(TP, 3) - rgc.collect() - if a: - assert not rgc.can_move(a) - return 0 - return 1 - except Exception, e: - return 2 + #try: + from pypy.rlib import rgc + a = rgc.malloc_nonmovable(TP, 3) + rgc.collect() + if a: + assert not rgc.can_move(a) + return 0 + return 1 + #except Exception, e: + # return 2 run = self.runner(func) - assert int(self.GC_CAN_MOVE) == run([]) + assert int(self.GC_CANNOT_MALLOC_NONMOVABLE) == run([]) def test_malloc_nonmovable_fixsize(self): S = lltype.GcStruct('S', ('x', lltype.Float)) @@ -489,7 +491,7 @@ return 2 run = self.runner(func) - assert run([]) == int(self.GC_CAN_MOVE) + assert run([]) == int(self.GC_CANNOT_MALLOC_NONMOVABLE) def test_resizable_buffer(self): from pypy.rpython.lltypesystem.rstr import STR @@ -506,8 +508,26 @@ run = self.runner(f) assert run([]) == 1 + def test_string_builder_over_allocation(self): + import gc + def fn(): + s = StringBuilder(4) + s.append("abcd") + s.append("defg") + s.append("rty") + s.append_multiple_char('y', 1000) + gc.collect() + s.append_multiple_char('y', 1000) + res = s.build()[1000] + gc.collect() + return res + fn = self.runner(fn) + res = fn([]) + assert res == 'y' + class GenericMovingGCTests(GenericGCTests): GC_CAN_MOVE = True + GC_CANNOT_MALLOC_NONMOVABLE = True def test_many_ids(self): py.test.skip("fails for bad reasons in lltype.py :-(") @@ -956,6 +976,7 @@ class TestHybridGC(TestGenerationGC): gcname = "hybrid" + GC_CANNOT_MALLOC_NONMOVABLE = False class gcpolicy(gc.FrameworkGcPolicy): class transformerclass(framework.FrameworkGCTransformer): @@ -986,3 +1007,6 @@ run = self.runner(f, nbargs=2) res = run([100, 100]) assert res == 200 + + def test_malloc_nonmovable_fixsize(self): + py.test.skip("not supported") Modified: pypy/dist/pypy/rpython/ootypesystem/rbuilder.py ============================================================================== --- pypy/dist/pypy/rpython/ootypesystem/rbuilder.py (original) +++ pypy/dist/pypy/rpython/ootypesystem/rbuilder.py Mon May 26 19:08:10 2008 @@ -1,10 +1,16 @@ from pypy.rpython.rbuilder import AbstractStringBuilderRepr from pypy.rpython.ootypesystem import ootype +from pypy.rpython.ootypesystem.rstr import string_repr, char_repr,\ + unicode_repr, unichar_repr + +MAX = 16*1024*1024 class BaseBuilderRepr(AbstractStringBuilderRepr): @classmethod def ll_new(cls, init_size): + if init_size < 0 or init_size > MAX: + init_size = MAX return ootype.new(cls.lowleveltype) @staticmethod @@ -32,9 +38,13 @@ class StringBuilderRepr(BaseBuilderRepr): lowleveltype = ootype.StringBuilder + string_repr = string_repr + char_repr = char_repr class UnicodeBuilderRepr(BaseBuilderRepr): lowleveltype = ootype.UnicodeBuilder + string_repr = unicode_repr + char_repr = unichar_repr stringbuilder_repr = StringBuilderRepr() unicodebuilder_repr = UnicodeBuilderRepr() Modified: pypy/dist/pypy/rpython/ootypesystem/rlist.py ============================================================================== --- pypy/dist/pypy/rpython/ootypesystem/rlist.py (original) +++ pypy/dist/pypy/rpython/ootypesystem/rlist.py Mon May 26 19:08:10 2008 @@ -71,7 +71,7 @@ def _make_empty_type(self): return ootype.List() - def _generate_newlist(self, llops, items_v, v_sizehint): + def _generate_newlist(self, llops, items_v): c_list = inputconst(ootype.Void, self.lowleveltype) v_result = llops.genop("new", [c_list], resulttype=self.lowleveltype) c_resize = inputconst(ootype.Void, "_ll_resize") @@ -88,9 +88,8 @@ -def newlist(llops, r_list, items_v, v_sizehint=None): - # XXX do something about v_sizehint - v_result = r_list._generate_newlist(llops, items_v, v_sizehint) +def newlist(llops, r_list, items_v): + v_result = r_list._generate_newlist(llops, items_v) c_setitem = inputconst(ootype.Void, "ll_setitem_fast") for i, v_item in enumerate(items_v): @@ -120,7 +119,7 @@ def make_iterator_repr(self): return ListIteratorRepr(self) - def _generate_newlist(self, llops, items_v, v_sizehint): + def _generate_newlist(self, llops, items_v): c_array = inputconst(ootype.Void, self.lowleveltype) c_length = inputconst(ootype.Signed, len(items_v)) v_result = llops.genop("oonewarray", [c_array, c_length], resulttype=self.lowleveltype) Modified: pypy/dist/pypy/rpython/rbuilder.py ============================================================================== --- pypy/dist/pypy/rpython/rbuilder.py (original) +++ pypy/dist/pypy/rpython/rbuilder.py Mon May 26 19:08:10 2008 @@ -1,90 +1,43 @@ -from pypy.annotation.model import SomeObject, SomeString, s_None,\ - SomeChar, SomeInteger, SomeUnicodeCodePoint, SomeUnicodeString from pypy.rpython.rmodel import Repr from pypy.rpython.annlowlevel import llhelper from pypy.rpython.lltypesystem import lltype - -class SomeStringBuilder(SomeObject): - def __init__(self, init_size): - self.init_size = init_size - - def method_append(self, s_str): - assert isinstance(s_str, (SomeString, SomeChar)) - return s_None - - def method_append_slice(self, s_str, s_start, s_end): - assert isinstance(s_str, SomeString) - assert isinstance(s_start, SomeInteger) - assert isinstance(s_end, SomeInteger) - assert s_start.nonneg - assert s_end.nonneg - return s_None - - def method_append_multiple_char(self, s_char, s_times): - assert isinstance(s_char, SomeChar) - assert isinstance(s_times, SomeInteger) - assert s_times.nonneg - return s_None - - def method_build(self): - return SomeString() - - def rtyper_makerepr(self, rtyper): - return rtyper.type_system.rbuilder.stringbuilder_repr - -class SomeUnicodeBuilder(SomeObject): - def __init__(self, init_size): - self.init_size = init_size - - def method_append(self, s_str): - assert isinstance(s_str, (SomeUnicodeCodePoint, SomeUnicodeString)) - return s_None - - def method_append_slice(self, s_str, s_start, s_end): - assert isinstance(s_str, SomeUnicodeString) - assert isinstance(s_start, SomeInteger) - assert isinstance(s_end, SomeInteger) - assert s_start.nonneg - assert s_end.nonneg - return s_None - - def method_append_multiple_char(self, s_char, s_times): - assert isinstance(s_char, SomeUnicodeCodePoint) - assert isinstance(s_times, SomeInteger) - assert s_times.nonneg - return s_None - - def method_build(self): - return SomeUnicodeString() - - def rtyper_makerepr(self, rtyper): - return rtyper.type_system.rbuilder.unicodebuilder_repr +from pypy.rlib.rstring import INIT_SIZE +from pypy.annotation.model import SomeChar, SomeUnicodeCodePoint class AbstractStringBuilderRepr(Repr): def rtyper_new(self, hop): repr = hop.r_result if len(hop.args_v) == 0: - v_arg = hop.inputconst(lltype.Signed, hop.s_result.init_size) + v_arg = hop.inputconst(lltype.Signed, INIT_SIZE) else: v_arg = hop.inputarg(lltype.Signed, 0) + hop.exception_cannot_occur() return hop.gendirectcall(self.ll_new, v_arg) def rtype_method_append(self, hop): - vlist = hop.inputargs(*hop.args_r) if isinstance(hop.args_s[1], (SomeChar, SomeUnicodeCodePoint)): - return hop.gendirectcall(self.ll_append_char, *vlist) - return hop.gendirectcall(self.ll_append, *vlist) + vlist = hop.inputargs(self, self.char_repr) + func = self.ll_append_char + else: + vlist = hop.inputargs(self, self.string_repr) + func = self.ll_append + hop.exception_cannot_occur() + return hop.gendirectcall(func, *vlist) def rtype_method_append_slice(self, hop): - vlist = hop.inputargs(*hop.args_r) + vlist = hop.inputargs(self, self.string_repr, + lltype.Signed, lltype.Signed) + hop.exception_cannot_occur() return hop.gendirectcall(self.ll_append_slice, *vlist) def rtype_method_append_multiple_char(self, hop): - vlist = hop.inputargs(*hop.args_r) + vlist = hop.inputargs(self, self.char_repr, lltype.Signed) + hop.exception_cannot_occur() return hop.gendirectcall(self.ll_append_multiple_char, *vlist) def rtype_method_build(self, hop): - vlist = hop.inputargs(*hop.args_r) + vlist = hop.inputargs(self) + hop.exception_cannot_occur() return hop.gendirectcall(self.ll_build, *vlist) Modified: pypy/dist/pypy/rpython/rlist.py ============================================================================== --- pypy/dist/pypy/rpython/rlist.py (original) +++ pypy/dist/pypy/rpython/rlist.py Mon May 26 19:08:10 2008 @@ -312,7 +312,7 @@ return hop.genop('bool_not', [flag], resulttype=Bool) -def rtype_newlist(hop, v_sizehint=None): +def rtype_newlist(hop): nb_args = hop.nb_args r_list = hop.r_result if r_list == robject.pyobj_repr: # special case: SomeObject lists! @@ -326,8 +326,7 @@ return v_result r_listitem = r_list.item_repr items_v = [hop.inputarg(r_listitem, arg=i) for i in range(nb_args)] - return hop.rtyper.type_system.rlist.newlist(hop.llops, r_list, items_v, - v_sizehint=v_sizehint) + return hop.rtyper.type_system.rlist.newlist(hop.llops, r_list, items_v) def rtype_alloc_and_set(hop): r_list = hop.r_result Modified: pypy/dist/pypy/rpython/test/test_rlist.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rlist.py (original) +++ pypy/dist/pypy/rpython/test/test_rlist.py Mon May 26 19:08:10 2008 @@ -1354,18 +1354,5 @@ lis = self.interpret(fnpop, [i]) assert list_is_clear(lis, 3-i) - def test_hints(self): - from pypy.rlib.objectmodel import newlist - from pypy.rpython.annlowlevel import hlstr - - def f(z): - z = hlstr(z) - x = newlist(sizehint=13) - x += z - return ''.join(x) - - res = self.interpret(f, [self.string_to_ll('abc')]) - assert self.ll_to_string(res) == 'abc' - class TestOOtype(BaseTestRlist, OORtypeMixin): rlist = oo_rlist Modified: pypy/dist/pypy/translator/c/src/mem.h ============================================================================== --- pypy/dist/pypy/translator/c/src/mem.h (original) +++ pypy/dist/pypy/translator/c/src/mem.h Mon May 26 19:08:10 2008 @@ -77,6 +77,10 @@ #define OP_RAW_MALLOC_USAGE(size, r) r = size +#define OP_RAW_REALLOC_SHRINK(p, old_size, size, r) r = PyObject_Realloc((void*)p, size) + +#define OP_RAW_REALLOC_GROW(p, old_size, size, r) r = PyObject_Realloc((void*)p, size) + #ifdef MS_WINDOWS #define alloca _alloca #endif Modified: pypy/dist/pypy/translator/c/test/test_boehm.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_boehm.py (original) +++ pypy/dist/pypy/translator/c/test/test_boehm.py Mon May 26 19:08:10 2008 @@ -377,6 +377,23 @@ c_fn = self.getcompiled(fn, []) assert c_fn() == False + def test_malloc_nonmovable(self): + TP = lltype.GcArray(lltype.Char) + def func(): + try: + from pypy.rlib import rgc + a = rgc.malloc_nonmovable(TP, 3) + rgc.collect() + if a: + assert not rgc.can_move(a) + return 0 + return 1 + except Exception, e: + return 2 + + run = self.getcompiled(func) + assert run() == 0 + def test_resizable_buffer(self): from pypy.rpython.lltypesystem.rstr import STR from pypy.rpython.annlowlevel import hlstr Modified: pypy/dist/pypy/translator/c/test/test_newgc.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_newgc.py (original) +++ pypy/dist/pypy/translator/c/test/test_newgc.py Mon May 26 19:08:10 2008 @@ -12,6 +12,7 @@ from pypy.rpython.lltypesystem.lloperation import llop from pypy.rpython.memory.test import snippet from pypy.rlib.objectmodel import keepalive_until_here +from pypy.rlib.rstring import StringBuilder, UnicodeBuilder from pypy import conftest from pypy.tool.udir import udir @@ -285,6 +286,8 @@ class TestUsingFramework(AbstractGCTestClass): gcpolicy = "marksweep" should_be_moving = False + GC_CAN_MOVE = False + GC_CANNOT_MALLOC_NONMOVABLE = False # interface for snippet.py large_tests_ok = True @@ -885,11 +888,54 @@ c_fn = self.getcompiled(f) assert c_fn() == 1 + + def test_can_move(self): + from pypy.rlib import rgc + class A: + pass + def fn(): + return rgc.can_move(A()) + + c_fn = self.getcompiled(fn, []) + assert c_fn() == self.GC_CAN_MOVE + + def test_malloc_nonmovable(self): + TP = lltype.GcArray(lltype.Char) + def func(): + try: + from pypy.rlib import rgc + a = rgc.malloc_nonmovable(TP, 3) + rgc.collect() + if a: + assert not rgc.can_move(a) + return 0 + return 1 + except Exception, e: + return 2 + + run = self.getcompiled(func) + assert run() == self.GC_CANNOT_MALLOC_NONMOVABLE + + def test_resizable_buffer(self): + from pypy.rpython.lltypesystem.rstr import STR + from pypy.rpython.annlowlevel import hlstr + from pypy.rlib import rgc + + def f(): + ptr = rgc.resizable_buffer_of_shape(STR, 2) + ptr.chars[0] = 'a' + ptr = rgc.resize_buffer(ptr, 1, 200) + ptr.chars[1] = 'b' + return hlstr(rgc.finish_building_buffer(ptr, 2)) == "ab" + run = self.getcompiled(f) + assert run() == True class TestSemiSpaceGC(TestUsingFramework, snippet.SemiSpaceGCTests): gcpolicy = "semispace" should_be_moving = True + GC_CAN_MOVE = True + GC_CANNOT_MALLOC_NONMOVABLE = True def test_many_ids(self): from pypy.rlib.objectmodel import compute_unique_id @@ -941,6 +987,35 @@ c_fn = self.getcompiled(fn) res = c_fn() assert res == 2 + + def test_string_builder(self): + def fn(): + s = StringBuilder() + s.append("a") + s.append("abc") + s.append_slice("abc", 1, 2) + s.append_multiple_char('d', 4) + return s.build() + c_fn = self.getcompiled(fn) + res = c_fn() + assert res == "aabcbdddd" + + def test_string_builder_over_allocation(self): + import gc + def fn(): + s = StringBuilder(4) + s.append("abcd") + s.append("defg") + s.append("rty") + s.append_multiple_char('y', 1000) + gc.collect() + s.append_multiple_char('y', 1000) + res = s.build() + gc.collect() + return res + c_fn = self.getcompiled(fn) + res = c_fn() + assert res[1000] == 'y' class TestGenerationalGC(TestSemiSpaceGC): gcpolicy = "generation" @@ -949,6 +1024,7 @@ class TestHybridGC(TestGenerationalGC): gcpolicy = "hybrid" should_be_moving = True + GC_CANNOT_MALLOC_NONMOVABLE = False def test_gc_set_max_heap_size(self): py.test.skip("not implemented") From fijal at codespeak.net Mon May 26 19:11:02 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 26 May 2008 19:11:02 +0200 (CEST) Subject: [pypy-svn] r55252 - pypy/dist/pypy/rpython/memory/gc Message-ID: <20080526171102.7571D2A80AD@codespeak.net> Author: fijal Date: Mon May 26 19:11:01 2008 New Revision: 55252 Modified: pypy/dist/pypy/rpython/memory/gc/hybrid.py Log: Disable reallocation for hybrid gc by default Modified: pypy/dist/pypy/rpython/memory/gc/hybrid.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gc/hybrid.py (original) +++ pypy/dist/pypy/rpython/memory/gc/hybrid.py Mon May 26 19:11:01 2008 @@ -81,7 +81,7 @@ """ first_unused_gcflag = _gcflag_next_bit prebuilt_gc_objects_are_static_roots = True - can_realloc = True + can_realloc = False # the following values override the default arguments of __init__ when # translating to a real backend. From fijal at codespeak.net Mon May 26 19:52:49 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 26 May 2008 19:52:49 +0200 (CEST) Subject: [pypy-svn] r55272 - pypy/dist/pypy/config Message-ID: <20080526175249.5FBC32A80B0@codespeak.net> Author: fijal Date: Mon May 26 19:52:47 2008 New Revision: 55272 Modified: pypy/dist/pypy/config/pypyoption.py Log: Add zipimport to allworkingmodules Modified: pypy/dist/pypy/config/pypyoption.py ============================================================================== --- pypy/dist/pypy/config/pypyoption.py (original) +++ pypy/dist/pypy/config/pypyoption.py Mon May 26 19:52:47 2008 @@ -24,7 +24,7 @@ working_modules = default_modules.copy() working_modules.update(dict.fromkeys( ["_socket", "unicodedata", "mmap", "fcntl", - "rctime" , "select", + "rctime" , "select", "zipimport", "crypt", "signal", "dyngram", "_rawffi", "termios", "zlib", "struct", "md5", "sha", "bz2", "_minimal_curses", "cStringIO"] )) From fijal at codespeak.net Mon May 26 20:04:26 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 26 May 2008 20:04:26 +0200 (CEST) Subject: [pypy-svn] r55273 - in pypy/dist/pypy/module/zipimport: . test Message-ID: <20080526180426.7E26D2A80B4@codespeak.net> Author: fijal Date: Mon May 26 20:04:23 2008 New Revision: 55273 Modified: pypy/dist/pypy/module/zipimport/interp_zipimport.py pypy/dist/pypy/module/zipimport/test/test_zipimport.py Log: The problem with TDD is that you need to know what are you testing first, apparently get_data can receive an absolute path. Modified: pypy/dist/pypy/module/zipimport/interp_zipimport.py ============================================================================== --- pypy/dist/pypy/module/zipimport/interp_zipimport.py (original) +++ pypy/dist/pypy/module/zipimport/interp_zipimport.py Mon May 26 20:04:23 2008 @@ -131,6 +131,15 @@ def getprefix(space, self): return space.wrap(self.prefix) + def _find_relative_path(self, filename): + if filename.startswith(self.dir.filename): + filename = filename[len(self.dir.filename):] + if filename.startswith(os.sep): + filename = filename[1:] + if ZIPSEP != os.path.sep: + filename = filename.replace(os.path.sep, ZIPSEP) + return filename + def import_py_file(self, space, modname, filename, buf, pkgpath): w = space.wrap w_mod = w(Module(space, w(modname))) @@ -248,8 +257,7 @@ load_module.unwrap_spec = ['self', ObjSpace, str] def get_data(self, space, filename): - if ZIPSEP != os.path.sep: - filename = filename.replace(os.path.sep, ZIPSEP) + filename = self._find_relative_path(filename) w = space.wrap try: return w(self.dir.read(filename)) Modified: pypy/dist/pypy/module/zipimport/test/test_zipimport.py ============================================================================== --- pypy/dist/pypy/module/zipimport/test/test_zipimport.py (original) +++ pypy/dist/pypy/module/zipimport/test/test_zipimport.py Mon May 26 20:04:23 2008 @@ -203,7 +203,7 @@ self.writefile(self, "yy.py", "3") self.writefile(self, 'uu.pyc', self.test_pyc) z = zipimport.zipimporter(self.zipfile) - assert z.get_data("xxx") == data + assert z.get_data(self.zipfile + os.sep + "xxx") == data assert z.is_package("xx") assert not z.is_package("yy") assert z.get_source("yy") == '3' From fijal at codespeak.net Mon May 26 20:28:19 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 26 May 2008 20:28:19 +0200 (CEST) Subject: [pypy-svn] r55274 - in pypy/dist/pypy/module/_weakref: . test Message-ID: <20080526182819.EBE4C2A809F@codespeak.net> Author: fijal Date: Mon May 26 20:28:17 2008 New Revision: 55274 Modified: pypy/dist/pypy/module/_weakref/interp__weakref.py pypy/dist/pypy/module/_weakref/test/test_weakref.py Log: A test and a fix Modified: pypy/dist/pypy/module/_weakref/interp__weakref.py ============================================================================== --- pypy/dist/pypy/module/_weakref/interp__weakref.py (original) +++ pypy/dist/pypy/module/_weakref/interp__weakref.py Mon May 26 20:28:17 2008 @@ -150,7 +150,14 @@ w_obj.setweakref(space, lifeline) return lifeline.get_or_make_weakref(space, w_subtype, w_obj, w_callable) -def descr__eq__(space, ref1, ref2): +def descr__eq__(space, ref1, w_ref2): + try: + ref2 = space.interp_w(W_Weakref, w_ref2) + except OperationError, o: + # should never happen, but be sure + if not o.match(space, space.w_TypeError): + raise + return space.wrap(False) w_obj1 = ref1.dereference() w_obj2 = ref2.dereference() if (w_obj1 is None or @@ -158,8 +165,8 @@ return space.is_(ref1, ref2) return space.eq(w_obj1, w_obj2) -def descr__ne__(space, ref1, ref2): - return space.not_(space.eq(ref1, ref2)) +def descr__ne__(space, ref1, w_ref2): + return space.not_(space.eq(ref1, w_ref2)) def descr__repr__(space, ref): w_obj = ref.dereference() @@ -182,9 +189,9 @@ is about to be finalized.""", __new__ = interp2app(descr__new__weakref), __eq__ = interp2app(descr__eq__, - unwrap_spec=[ObjSpace, W_Weakref, W_Weakref]), + unwrap_spec=[ObjSpace, W_Weakref, W_Root]), __ne__ = interp2app(descr__ne__, - unwrap_spec=[ObjSpace, W_Weakref, W_Weakref]), + unwrap_spec=[ObjSpace, W_Weakref, W_Root]), __hash__ = interp2app(W_Weakref.descr_hash, unwrap_spec=['self']), __repr__ = reprdescr, __call__ = interp2app(W_Weakref.descr_call, unwrap_spec=['self']) Modified: pypy/dist/pypy/module/_weakref/test/test_weakref.py ============================================================================== --- pypy/dist/pypy/module/_weakref/test/test_weakref.py (original) +++ pypy/dist/pypy/module/_weakref/test/test_weakref.py Mon May 26 20:28:17 2008 @@ -384,3 +384,12 @@ s = repr(w) print s assert "dead" in s + + def test_eq(self): + import _weakref + class A(object): + pass + + a = A() + assert not(_weakref.ref(a) == a) + assert _weakref.ref(a) != a From fijal at codespeak.net Mon May 26 20:38:55 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 26 May 2008 20:38:55 +0200 (CEST) Subject: [pypy-svn] r55275 - in pypy/dist/pypy/module/_weakref: . test Message-ID: <20080526183855.22ECE2A809F@codespeak.net> Author: fijal Date: Mon May 26 20:38:52 2008 New Revision: 55275 Modified: pypy/dist/pypy/module/_weakref/interp__weakref.py pypy/dist/pypy/module/_weakref/test/test_weakref.py Log: * A test and a fix * Use isinstance instead of interp_w, simplifies code and I don't see how we can run into problems there. Modified: pypy/dist/pypy/module/_weakref/interp__weakref.py ============================================================================== --- pypy/dist/pypy/module/_weakref/interp__weakref.py (original) +++ pypy/dist/pypy/module/_weakref/interp__weakref.py Mon May 26 20:38:52 2008 @@ -151,13 +151,9 @@ return lifeline.get_or_make_weakref(space, w_subtype, w_obj, w_callable) def descr__eq__(space, ref1, w_ref2): - try: - ref2 = space.interp_w(W_Weakref, w_ref2) - except OperationError, o: - # should never happen, but be sure - if not o.match(space, space.w_TypeError): - raise - return space.wrap(False) + if not isinstance(w_ref2, W_Weakref): + return space.w_NotImplemented + ref2 = w_ref2 w_obj1 = ref1.dereference() w_obj2 = ref2.dereference() if (w_obj1 is None or Modified: pypy/dist/pypy/module/_weakref/test/test_weakref.py ============================================================================== --- pypy/dist/pypy/module/_weakref/test/test_weakref.py (original) +++ pypy/dist/pypy/module/_weakref/test/test_weakref.py Mon May 26 20:38:52 2008 @@ -393,3 +393,11 @@ a = A() assert not(_weakref.ref(a) == a) assert _weakref.ref(a) != a + + class A(object): + def __eq__(self, other): + return True + + a = A() + assert _weakref.ref(a) == a + From fijal at codespeak.net Mon May 26 20:59:07 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 26 May 2008 20:59:07 +0200 (CEST) Subject: [pypy-svn] r55277 - pypy/dist/pypy/rlib Message-ID: <20080526185907.61D0316856C@codespeak.net> Author: fijal Date: Mon May 26 20:59:06 2008 New Revision: 55277 Modified: pypy/dist/pypy/rlib/rzipfile.py Log: Wuaa, forgotten commit Modified: pypy/dist/pypy/rlib/rzipfile.py ============================================================================== --- pypy/dist/pypy/rlib/rzipfile.py (original) +++ pypy/dist/pypy/rlib/rzipfile.py Mon May 26 20:59:06 2008 @@ -182,6 +182,8 @@ (x.create_version, x.create_system, x.extract_version, x.reserved, x.flag_bits, x.compress_type, t, d, x.CRC, x.compress_size, x.file_size) = centdir[1:12] + x.dostime = t + x.dosdate = d x.volume, x.internal_attr, x.external_attr = centdir[15:18] # Convert date/time code to (year, month, day, hour, min, sec) x.date_time = ( (d>>9)+1980, (d>>5)&0xF, d&0x1F, From antocuni at codespeak.net Mon May 26 21:40:51 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Mon, 26 May 2008 21:40:51 +0200 (CEST) Subject: [pypy-svn] r55278 - pypy/django/tests Message-ID: <20080526194051.62FD2169E9F@codespeak.net> Author: antocuni Date: Mon May 26 21:40:48 2008 New Revision: 55278 Added: pypy/django/tests/failures.txt (contents, props changed) Log: a log with the tests I tried/fixed Added: pypy/django/tests/failures.txt ============================================================================== --- (empty file) +++ pypy/django/tests/failures.txt Mon May 26 21:40:48 2008 @@ -0,0 +1,22 @@ +Tests failing because of missing expat (xml parser) +--------------------------------------------------- + + - modeltests/fixtures + + - modeltests/serializers + + - regressiontests/fixtures_regress + +(maybe there are other issues, but they are masked by xml errors) + + +Other tests +----------- + +"some tests" fixed in r54740 (XXX: which are +"some tests") + +regressiontests/datastructures fixed in r55068 + +regressiontests/forms/widget_tests and others fixed in r55075 + From fijal at codespeak.net Mon May 26 21:51:32 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 26 May 2008 21:51:32 +0200 (CEST) Subject: [pypy-svn] r55279 - pypy/django/tests Message-ID: <20080526195132.E415C2A80AB@codespeak.net> Author: fijal Date: Mon May 26 21:51:31 2008 New Revision: 55279 Modified: pypy/django/tests/failures.txt Log: update failures Modified: pypy/django/tests/failures.txt ============================================================================== --- pypy/django/tests/failures.txt (original) +++ pypy/django/tests/failures.txt Mon May 26 21:51:31 2008 @@ -20,3 +20,31 @@ regressiontests/forms/widget_tests and others fixed in r55075 +As of 26 May 2008 +================= + +modeltests/test_client + + one test requires pyexpat + +regressiontests/serializers_regress/tests/SerializerTests/ + test_xml_serializer + test_xml_serializer_fields + + requires pyexpat + +fixtures - requires pyexpat +modeltests/serializers - requires pyexpat (can hide further errors, hard to tell) + +regressiontests.i18n.tests.__test__.regressions - module print + +regressiontests.forms.tests.__test__.form_tests - pyexpat + +regressiontests.dispatch.tests.test_dispatcher.DispatcherTests - garbage collection not happening immediately + +doctest regressiontests.datastructures.tests[45] - dict subclasses + +regressiontests.httpwrappers.tests - dict subclasses + +regressiontests.templates.tests.Templates - pyexpat + From fijal at codespeak.net Mon May 26 22:36:11 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 26 May 2008 22:36:11 +0200 (CEST) Subject: [pypy-svn] r55280 - pypy/dist/lib-python/modified-2.4.1/test Message-ID: <20080526203611.B23A92A809F@codespeak.net> Author: fijal Date: Mon May 26 22:36:09 2008 New Revision: 55280 Added: pypy/dist/lib-python/modified-2.4.1/test/test_pyexpat.py (contents, props changed) Log: Add newer test than in cpython's lib (from cpython's trunk). It's written in much saner style Added: pypy/dist/lib-python/modified-2.4.1/test/test_pyexpat.py ============================================================================== --- (empty file) +++ pypy/dist/lib-python/modified-2.4.1/test/test_pyexpat.py Mon May 26 22:36:09 2008 @@ -0,0 +1,575 @@ +# XXX TypeErrors on calling handlers, or on bad return values from a +# handler, are obscure and unhelpful. + +import StringIO, sys +import unittest + +import pyexpat +from xml.parsers import expat + +from test.test_support import sortdict, run_unittest + + +class SetAttributeTest(unittest.TestCase): + def setUp(self): + self.parser = expat.ParserCreate(namespace_separator='!') + self.set_get_pairs = [ + [0, 0], + [1, 1], + [2, 1], + [0, 0], + ] + + def test_returns_unicode(self): + for x, y in self.set_get_pairs: + self.parser.returns_unicode = x + self.assertEquals(self.parser.returns_unicode, y) + + def test_ordered_attributes(self): + for x, y in self.set_get_pairs: + self.parser.ordered_attributes = x + self.assertEquals(self.parser.ordered_attributes, y) + + def test_specified_attributes(self): + for x, y in self.set_get_pairs: + self.parser.specified_attributes = x + self.assertEquals(self.parser.specified_attributes, y) + + +data = '''\ + + + + + + + + +%unparsed_entity; +]> + + + + Contents of subelements + + +&external_entity; + +''' + + +# Produce UTF-8 output +class ParseTest(unittest.TestCase): + class Outputter: + def __init__(self): + self.out = [] + + def StartElementHandler(self, name, attrs): + self.out.append('Start element: ' + repr(name) + ' ' + + sortdict(attrs)) + + def EndElementHandler(self, name): + self.out.append('End element: ' + repr(name)) + + def CharacterDataHandler(self, data): + data = data.strip() + if data: + self.out.append('Character data: ' + repr(data)) + + def ProcessingInstructionHandler(self, target, data): + self.out.append('PI: ' + repr(target) + ' ' + repr(data)) + + def StartNamespaceDeclHandler(self, prefix, uri): + self.out.append('NS decl: ' + repr(prefix) + ' ' + repr(uri)) + + def EndNamespaceDeclHandler(self, prefix): + self.out.append('End of NS decl: ' + repr(prefix)) + + def StartCdataSectionHandler(self): + self.out.append('Start of CDATA section') + + def EndCdataSectionHandler(self): + self.out.append('End of CDATA section') + + def CommentHandler(self, text): + self.out.append('Comment: ' + repr(text)) + + def NotationDeclHandler(self, *args): + name, base, sysid, pubid = args + self.out.append('Notation declared: %s' %(args,)) + + def UnparsedEntityDeclHandler(self, *args): + entityName, base, systemId, publicId, notationName = args + self.out.append('Unparsed entity decl: %s' %(args,)) + + def NotStandaloneHandler(self, userData): + self.out.append('Not standalone') + return 1 + + def ExternalEntityRefHandler(self, *args): + context, base, sysId, pubId = args + self.out.append('External entity ref: %s' %(args[1:],)) + return 1 + + def DefaultHandler(self, userData): + pass + + def DefaultHandlerExpand(self, userData): + pass + + handler_names = [ + 'StartElementHandler', 'EndElementHandler', + 'CharacterDataHandler', 'ProcessingInstructionHandler', + 'UnparsedEntityDeclHandler', 'NotationDeclHandler', + 'StartNamespaceDeclHandler', 'EndNamespaceDeclHandler', + 'CommentHandler', 'StartCdataSectionHandler', + 'EndCdataSectionHandler', + 'DefaultHandler', 'DefaultHandlerExpand', + #'NotStandaloneHandler', + 'ExternalEntityRefHandler' + ] + + def test_utf8(self): + + out = self.Outputter() + parser = expat.ParserCreate(namespace_separator='!') + for name in self.handler_names: + setattr(parser, name, getattr(out, name)) + parser.returns_unicode = 0 + parser.Parse(data, 1) + + # Verify output + op = out.out + self.assertEquals(op[0], 'PI: \'xml-stylesheet\' \'href="stylesheet.css"\'') + self.assertEquals(op[1], "Comment: ' comment data '") + self.assertEquals(op[2], "Notation declared: ('notation', None, 'notation.jpeg', None)") + self.assertEquals(op[3], "Unparsed entity decl: ('unparsed_entity', None, 'entity.file', None, 'notation')") + self.assertEquals(op[4], "Start element: 'root' {'attr1': 'value1', 'attr2': 'value2\\xe1\\xbd\\x80'}") + self.assertEquals(op[5], "NS decl: 'myns' 'http://www.python.org/namespace'") + self.assertEquals(op[6], "Start element: 'http://www.python.org/namespace!subelement' {}") + self.assertEquals(op[7], "Character data: 'Contents of subelements'") + self.assertEquals(op[8], "End element: 'http://www.python.org/namespace!subelement'") + self.assertEquals(op[9], "End of NS decl: 'myns'") + self.assertEquals(op[10], "Start element: 'sub2' {}") + self.assertEquals(op[11], 'Start of CDATA section') + self.assertEquals(op[12], "Character data: 'contents of CDATA section'") + self.assertEquals(op[13], 'End of CDATA section') + self.assertEquals(op[14], "End element: 'sub2'") + self.assertEquals(op[15], "External entity ref: (None, 'entity.file', None)") + self.assertEquals(op[16], "End element: 'root'") + + def test_unicode(self): + # Try the parse again, this time producing Unicode output + out = self.Outputter() + parser = expat.ParserCreate(namespace_separator='!') + parser.returns_unicode = 1 + for name in self.handler_names: + setattr(parser, name, getattr(out, name)) + + parser.Parse(data, 1) + + op = out.out + self.assertEquals(op[0], 'PI: u\'xml-stylesheet\' u\'href="stylesheet.css"\'') + self.assertEquals(op[1], "Comment: u' comment data '") + self.assertEquals(op[2], "Notation declared: (u'notation', None, u'notation.jpeg', None)") + self.assertEquals(op[3], "Unparsed entity decl: (u'unparsed_entity', None, u'entity.file', None, u'notation')") + self.assertEquals(op[4], "Start element: u'root' {u'attr1': u'value1', u'attr2': u'value2\\u1f40'}") + self.assertEquals(op[5], "NS decl: u'myns' u'http://www.python.org/namespace'") + self.assertEquals(op[6], "Start element: u'http://www.python.org/namespace!subelement' {}") + self.assertEquals(op[7], "Character data: u'Contents of subelements'") + self.assertEquals(op[8], "End element: u'http://www.python.org/namespace!subelement'") + self.assertEquals(op[9], "End of NS decl: u'myns'") + self.assertEquals(op[10], "Start element: u'sub2' {}") + self.assertEquals(op[11], 'Start of CDATA section') + self.assertEquals(op[12], "Character data: u'contents of CDATA section'") + self.assertEquals(op[13], 'End of CDATA section') + self.assertEquals(op[14], "End element: u'sub2'") + self.assertEquals(op[15], "External entity ref: (None, u'entity.file', None)") + self.assertEquals(op[16], "End element: u'root'") + + def test_parse_file(self): + # Try parsing a file + out = self.Outputter() + parser = expat.ParserCreate(namespace_separator='!') + parser.returns_unicode = 1 + for name in self.handler_names: + setattr(parser, name, getattr(out, name)) + file = StringIO.StringIO(data) + + parser.ParseFile(file) + + op = out.out + self.assertEquals(op[0], 'PI: u\'xml-stylesheet\' u\'href="stylesheet.css"\'') + self.assertEquals(op[1], "Comment: u' comment data '") + self.assertEquals(op[2], "Notation declared: (u'notation', None, u'notation.jpeg', None)") + self.assertEquals(op[3], "Unparsed entity decl: (u'unparsed_entity', None, u'entity.file', None, u'notation')") + self.assertEquals(op[4], "Start element: u'root' {u'attr1': u'value1', u'attr2': u'value2\\u1f40'}") + self.assertEquals(op[5], "NS decl: u'myns' u'http://www.python.org/namespace'") + self.assertEquals(op[6], "Start element: u'http://www.python.org/namespace!subelement' {}") + self.assertEquals(op[7], "Character data: u'Contents of subelements'") + self.assertEquals(op[8], "End element: u'http://www.python.org/namespace!subelement'") + self.assertEquals(op[9], "End of NS decl: u'myns'") + self.assertEquals(op[10], "Start element: u'sub2' {}") + self.assertEquals(op[11], 'Start of CDATA section') + self.assertEquals(op[12], "Character data: u'contents of CDATA section'") + self.assertEquals(op[13], 'End of CDATA section') + self.assertEquals(op[14], "End element: u'sub2'") + self.assertEquals(op[15], "External entity ref: (None, u'entity.file', None)") + self.assertEquals(op[16], "End element: u'root'") + + +class NamespaceSeparatorTest(unittest.TestCase): + def test_legal(self): + # Tests that make sure we get errors when the namespace_separator value + # is illegal, and that we don't for good values: + expat.ParserCreate() + expat.ParserCreate(namespace_separator=None) + expat.ParserCreate(namespace_separator=' ') + + def test_illegal(self): + try: + expat.ParserCreate(namespace_separator=42) + self.fail() + except TypeError, e: + self.assertEquals(str(e), + 'ParserCreate() argument 2 must be string or None, not int') + + try: + expat.ParserCreate(namespace_separator='too long') + self.fail() + except ValueError, e: + self.assertEquals(str(e), + 'namespace_separator must be at most one character, omitted, or None') + + def test_zero_length(self): + # ParserCreate() needs to accept a namespace_separator of zero length + # to satisfy the requirements of RDF applications that are required + # to simply glue together the namespace URI and the localname. Though + # considered a wart of the RDF specifications, it needs to be supported. + # + # See XML-SIG mailing list thread starting with + # http://mail.python.org/pipermail/xml-sig/2001-April/005202.html + # + expat.ParserCreate(namespace_separator='') # too short + + +class InterningTest(unittest.TestCase): + def test(self): + # Test the interning machinery. + p = expat.ParserCreate() + L = [] + def collector(name, *args): + L.append(name) + p.StartElementHandler = collector + p.EndElementHandler = collector + p.Parse(" ", 1) + tag = L[0] + self.assertEquals(len(L), 6) + for entry in L: + # L should have the same string repeated over and over. + self.assertTrue(tag is entry) + + +class BufferTextTest(unittest.TestCase): + def setUp(self): + self.stuff = [] + self.parser = expat.ParserCreate() + self.parser.buffer_text = 1 + self.parser.CharacterDataHandler = self.CharacterDataHandler + + def check(self, expected, label): + self.assertEquals(self.stuff, expected, + "%s\nstuff = %r\nexpected = %r" + % (label, self.stuff, map(unicode, expected))) + + def CharacterDataHandler(self, text): + self.stuff.append(text) + + def StartElementHandler(self, name, attrs): + self.stuff.append("<%s>" % name) + bt = attrs.get("buffer-text") + if bt == "yes": + self.parser.buffer_text = 1 + elif bt == "no": + self.parser.buffer_text = 0 + + def EndElementHandler(self, name): + self.stuff.append("" % name) + + def CommentHandler(self, data): + self.stuff.append("" % data) + + def setHandlers(self, handlers=[]): + for name in handlers: + setattr(self.parser, name, getattr(self, name)) + + def test_default_to_disabled(self): + parser = expat.ParserCreate() + self.assertFalse(parser.buffer_text) + + def test_buffering_enabled(self): + # Make sure buffering is turned on + self.assertTrue(self.parser.buffer_text) + self.parser.Parse("123", 1) + self.assertEquals(self.stuff, ['123'], + "buffered text not properly collapsed") + + def test1(self): + # XXX This test exposes more detail of Expat's text chunking than we + # XXX like, but it tests what we need to concisely. + self.setHandlers(["StartElementHandler"]) + self.parser.Parse("12\n34\n5", 1) + self.assertEquals(self.stuff, + ["", "1", "", "2", "\n", "3", "", "4\n5"], + "buffering control not reacting as expected") + + def test2(self): + self.parser.Parse("1<2> \n 3", 1) + self.assertEquals(self.stuff, ["1<2> \n 3"], + "buffered text not properly collapsed") + + def test3(self): + self.setHandlers(["StartElementHandler"]) + self.parser.Parse("123", 1) + self.assertEquals(self.stuff, ["", "1", "", "2", "", "3"], + "buffered text not properly split") + + def test4(self): + self.setHandlers(["StartElementHandler", "EndElementHandler"]) + self.parser.CharacterDataHandler = None + self.parser.Parse("123", 1) + self.assertEquals(self.stuff, + ["", "", "", "", "", ""]) + + def test5(self): + self.setHandlers(["StartElementHandler", "EndElementHandler"]) + self.parser.Parse("123", 1) + self.assertEquals(self.stuff, + ["", "1", "", "", "2", "", "", "3", ""]) + + def test6(self): + self.setHandlers(["CommentHandler", "EndElementHandler", + "StartElementHandler"]) + self.parser.Parse("12345 ", 1) + self.assertEquals(self.stuff, + ["", "1", "", "", "2", "", "", "345", ""], + "buffered text not properly split") + + def test7(self): + self.setHandlers(["CommentHandler", "EndElementHandler", + "StartElementHandler"]) + self.parser.Parse("12345 ", 1) + self.assertEquals(self.stuff, + ["", "1", "", "", "2", "", "", "3", + "", "4", "", "5", ""], + "buffered text not properly split") + + +# Test handling of exception from callback: +class HandlerExceptionTest(unittest.TestCase): + def StartElementHandler(self, name, attrs): + raise RuntimeError(name) + + def test(self): + parser = expat.ParserCreate() + parser.StartElementHandler = self.StartElementHandler + try: + parser.Parse("", 1) + self.fail() + except RuntimeError, e: + self.assertEquals(e.args[0], 'a', + "Expected RuntimeError for element 'a', but" + \ + " found %r" % e.args[0]) + + +# Test Current* members: +class PositionTest(unittest.TestCase): + def StartElementHandler(self, name, attrs): + self.check_pos('s') + + def EndElementHandler(self, name): + self.check_pos('e') + + def check_pos(self, event): + pos = (event, + self.parser.CurrentByteIndex, + self.parser.CurrentLineNumber, + self.parser.CurrentColumnNumber) + self.assertTrue(self.upto < len(self.expected_list), + 'too many parser events') + expected = self.expected_list[self.upto] + self.assertEquals(pos, expected, + 'Expected position %s, got position %s' %(pos, expected)) + self.upto += 1 + + def test(self): + self.parser = expat.ParserCreate() + self.parser.StartElementHandler = self.StartElementHandler + self.parser.EndElementHandler = self.EndElementHandler + self.upto = 0 + self.expected_list = [('s', 0, 1, 0), ('s', 5, 2, 1), ('s', 11, 3, 2), + ('e', 15, 3, 6), ('e', 17, 4, 1), ('e', 22, 5, 0)] + + xml = '\n \n \n \n' + self.parser.Parse(xml, 1) + + +class sf1296433Test(unittest.TestCase): + def test_parse_only_xml_data(self): + # http://python.org/sf/1296433 + # + xml = "%s" % ('a' * 1025) + # this one doesn't crash + #xml = "%s" % ('a' * 10000) + + class SpecificException(Exception): + pass + + def handler(text): + raise SpecificException + + parser = expat.ParserCreate() + parser.CharacterDataHandler = handler + + self.assertRaises(Exception, parser.Parse, xml) + +class ChardataBufferTest(unittest.TestCase): + """ + test setting of chardata buffer size + """ + + def test_1025_bytes(self): + self.assertEquals(self.small_buffer_test(1025), 2) + + def test_1000_bytes(self): + self.assertEquals(self.small_buffer_test(1000), 1) + + def test_wrong_size(self): + parser = expat.ParserCreate() + parser.buffer_text = 1 + def f(size): + parser.buffer_size = size + + self.assertRaises(TypeError, f, sys.maxint+1) + self.assertRaises(ValueError, f, -1) + self.assertRaises(ValueError, f, 0) + + def test_unchanged_size(self): + xml1 = ("%s" % ('a' * 512)) + xml2 = 'a'*512 + '' + parser = expat.ParserCreate() + parser.CharacterDataHandler = self.counting_handler + parser.buffer_size = 512 + parser.buffer_text = 1 + + # Feed 512 bytes of character data: the handler should be called + # once. + self.n = 0 + parser.Parse(xml1) + self.assertEquals(self.n, 1) + + # Reassign to buffer_size, but assign the same size. + parser.buffer_size = parser.buffer_size + self.assertEquals(self.n, 1) + + # Try parsing rest of the document + parser.Parse(xml2) + self.assertEquals(self.n, 2) + + + def test_disabling_buffer(self): + xml1 = "%s" % ('a' * 512) + xml2 = ('b' * 1024) + xml3 = "%s" % ('c' * 1024) + parser = expat.ParserCreate() + parser.CharacterDataHandler = self.counting_handler + parser.buffer_text = 1 + parser.buffer_size = 1024 + self.assertEquals(parser.buffer_size, 1024) + + # Parse one chunk of XML + self.n = 0 + parser.Parse(xml1, 0) + self.assertEquals(parser.buffer_size, 1024) + self.assertEquals(self.n, 1) + + # Turn off buffering and parse the next chunk. + parser.buffer_text = 0 + self.assertFalse(parser.buffer_text) + self.assertEquals(parser.buffer_size, 1024) + for i in range(10): + parser.Parse(xml2, 0) + self.assertEquals(self.n, 11) + + parser.buffer_text = 1 + self.assertTrue(parser.buffer_text) + self.assertEquals(parser.buffer_size, 1024) + parser.Parse(xml3, 1) + self.assertEquals(self.n, 12) + + + + def make_document(self, bytes): + return ("" + bytes * 'a' + '') + + def counting_handler(self, text): + self.n += 1 + + def small_buffer_test(self, buffer_len): + xml = "%s" % ('a' * buffer_len) + parser = expat.ParserCreate() + parser.CharacterDataHandler = self.counting_handler + parser.buffer_size = 1024 + parser.buffer_text = 1 + + self.n = 0 + parser.Parse(xml) + return self.n + + def test_change_size_1(self): + xml1 = "%s" % ('a' * 1024) + xml2 = "aaa%s" % ('a' * 1025) + parser = expat.ParserCreate() + parser.CharacterDataHandler = self.counting_handler + parser.buffer_text = 1 + parser.buffer_size = 1024 + self.assertEquals(parser.buffer_size, 1024) + + self.n = 0 + parser.Parse(xml1, 0) + parser.buffer_size *= 2 + self.assertEquals(parser.buffer_size, 2048) + parser.Parse(xml2, 1) + self.assertEquals(self.n, 2) + + def test_change_size_2(self): + xml1 = "a%s" % ('a' * 1023) + xml2 = "aaa%s" % ('a' * 1025) + parser = expat.ParserCreate() + parser.CharacterDataHandler = self.counting_handler + parser.buffer_text = 1 + parser.buffer_size = 2048 + self.assertEquals(parser.buffer_size, 2048) + + self.n=0 + parser.Parse(xml1, 0) + parser.buffer_size /= 2 + self.assertEquals(parser.buffer_size, 1024) + parser.Parse(xml2, 1) + self.assertEquals(self.n, 4) + + +def test_main(): + run_unittest(SetAttributeTest, + ParseTest, + NamespaceSeparatorTest, + InterningTest, + BufferTextTest, + HandlerExceptionTest, + PositionTest, + sf1296433Test, + ChardataBufferTest) + +if __name__ == "__main__": + test_main() From fijal at codespeak.net Mon May 26 22:48:11 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 26 May 2008 22:48:11 +0200 (CEST) Subject: [pypy-svn] r55281 - pypy/dist/pypy/lib/app_test Message-ID: <20080526204811.C45552A809F@codespeak.net> Author: fijal Date: Mon May 26 22:48:10 2008 New Revision: 55281 Added: pypy/dist/pypy/lib/app_test/test_pyexpat.py (contents, props changed) Log: Port cpython's test suite to py.test one Added: pypy/dist/pypy/lib/app_test/test_pyexpat.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/lib/app_test/test_pyexpat.py Mon May 26 22:48:10 2008 @@ -0,0 +1,565 @@ +# XXX TypeErrors on calling handlers, or on bad return values from a +# handler, are obscure and unhelpful. + +import StringIO, sys +import unittest + +import pyexpat +from xml.parsers import expat + +from test.test_support import sortdict, run_unittest + +class TestSetAttribute: + def setup_method(self, meth): + self.parser = expat.ParserCreate(namespace_separator='!') + self.set_get_pairs = [ + [0, 0], + [1, 1], + [2, 1], + [0, 0], + ] + + def test_returns_unicode(self): + for x, y in self.set_get_pairs: + self.parser.returns_unicode = x + assert self.parser.returns_unicode == y + + def test_ordered_attributes(self): + for x, y in self.set_get_pairs: + self.parser.ordered_attributes = x + assert self.parser.ordered_attributes == y + + def test_specified_attributes(self): + for x, y in self.set_get_pairs: + self.parser.specified_attributes = x + assert self.parser.specified_attributes == y + + +data = '''\ + + + + + + + + +%unparsed_entity; +]> + + + + Contents of subelements + + +&external_entity; + +''' + +# Produce UTF-8 output +class TestParse: + class Outputter: + def __init__(self): + self.out = [] + + def StartElementHandler(self, name, attrs): + self.out.append('Start element: ' + repr(name) + ' ' + + sortdict(attrs)) + + def EndElementHandler(self, name): + self.out.append('End element: ' + repr(name)) + + def CharacterDataHandler(self, data): + data = data.strip() + if data: + self.out.append('Character data: ' + repr(data)) + + def ProcessingInstructionHandler(self, target, data): + self.out.append('PI: ' + repr(target) + ' ' + repr(data)) + + def StartNamespaceDeclHandler(self, prefix, uri): + self.out.append('NS decl: ' + repr(prefix) + ' ' + repr(uri)) + + def EndNamespaceDeclHandler(self, prefix): + self.out.append('End of NS decl: ' + repr(prefix)) + + def StartCdataSectionHandler(self): + self.out.append('Start of CDATA section') + + def EndCdataSectionHandler(self): + self.out.append('End of CDATA section') + + def CommentHandler(self, text): + self.out.append('Comment: ' + repr(text)) + + def NotationDeclHandler(self, *args): + name, base, sysid, pubid = args + self.out.append('Notation declared: %s' %(args,)) + + def UnparsedEntityDeclHandler(self, *args): + entityName, base, systemId, publicId, notationName = args + self.out.append('Unparsed entity decl: %s' %(args,)) + + def NotStandaloneHandler(self, userData): + self.out.append('Not standalone') + return 1 + + def ExternalEntityRefHandler(self, *args): + context, base, sysId, pubId = args + self.out.append('External entity ref: %s' %(args[1:],)) + return 1 + + def DefaultHandler(self, userData): + pass + + def DefaultHandlerExpand(self, userData): + pass + + handler_names = [ + 'StartElementHandler', 'EndElementHandler', + 'CharacterDataHandler', 'ProcessingInstructionHandler', + 'UnparsedEntityDeclHandler', 'NotationDeclHandler', + 'StartNamespaceDeclHandler', 'EndNamespaceDeclHandler', + 'CommentHandler', 'StartCdataSectionHandler', + 'EndCdataSectionHandler', + 'DefaultHandler', 'DefaultHandlerExpand', + #'NotStandaloneHandler', + 'ExternalEntityRefHandler' + ] + + def test_utf8(self): + + out = self.Outputter() + parser = expat.ParserCreate(namespace_separator='!') + for name in self.handler_names: + setattr(parser, name, getattr(out, name)) + parser.returns_unicode = 0 + parser.Parse(data, 1) + + # Verify output + op = out.out + assert op[0] == 'PI: \'xml-stylesheet\' \'href="stylesheet.css"\'' + assert op[1] == "Comment: ' comment data '" + assert op[2] == "Notation declared: ('notation', None, 'notation.jpeg', None)" + assert op[3] == "Unparsed entity decl: ('unparsed_entity', None, 'entity.file', None, 'notation')" + assert op[4] == "Start element: 'root' {'attr1': 'value1', 'attr2': 'value2\\xe1\\xbd\\x80'}" + assert op[5] == "NS decl: 'myns' 'http://www.python.org/namespace'" + assert op[6] == "Start element: 'http://www.python.org/namespace!subelement' {}" + assert op[7] == "Character data: 'Contents of subelements'" + assert op[8] == "End element: 'http://www.python.org/namespace!subelement'" + assert op[9] == "End of NS decl: 'myns'" + assert op[10] == "Start element: 'sub2' {}" + assert op[11] == 'Start of CDATA section' + assert op[12] == "Character data: 'contents of CDATA section'" + assert op[13] == 'End of CDATA section' + assert op[14] == "End element: 'sub2'" + assert op[15] == "External entity ref: (None, 'entity.file', None)" + assert op[16] == "End element: 'root'" + + def test_unicode(self): + # Try the parse again, this time producing Unicode output + out = self.Outputter() + parser = expat.ParserCreate(namespace_separator='!') + parser.returns_unicode = 1 + for name in self.handler_names: + setattr(parser, name, getattr(out, name)) + + parser.Parse(data, 1) + + op = out.out + assert op[0] == 'PI: u\'xml-stylesheet\' u\'href="stylesheet.css"\'' + assert op[1] == "Comment: u' comment data '" + assert op[2] == "Notation declared: (u'notation', None, u'notation.jpeg', None)" + assert op[3] == "Unparsed entity decl: (u'unparsed_entity', None, u'entity.file', None, u'notation')" + assert op[4] == "Start element: u'root' {u'attr1': u'value1', u'attr2': u'value2\\u1f40'}" + assert op[5] == "NS decl: u'myns' u'http://www.python.org/namespace'" + assert op[6] == "Start element: u'http://www.python.org/namespace!subelement' {}" + assert op[7] == "Character data: u'Contents of subelements'" + assert op[8] == "End element: u'http://www.python.org/namespace!subelement'" + assert op[9] == "End of NS decl: u'myns'" + assert op[10] == "Start element: u'sub2' {}" + assert op[11] == 'Start of CDATA section' + assert op[12] == "Character data: u'contents of CDATA section'" + assert op[13] == 'End of CDATA section' + assert op[14] == "End element: u'sub2'" + assert op[15] == "External entity ref: (None, u'entity.file', None)" + assert op[16] == "End element: u'root'" + + def test_parse_file(self): + # Try parsing a file + out = self.Outputter() + parser = expat.ParserCreate(namespace_separator='!') + parser.returns_unicode = 1 + for name in self.handler_names: + setattr(parser, name, getattr(out, name)) + file = StringIO.StringIO(data) + + parser.ParseFile(file) + + op = out.out + assert op[0] == 'PI: u\'xml-stylesheet\' u\'href="stylesheet.css"\'' + assert op[1] == "Comment: u' comment data '" + assert op[2] == "Notation declared: (u'notation', None, u'notation.jpeg', None)" + assert op[3] == "Unparsed entity decl: (u'unparsed_entity', None, u'entity.file', None, u'notation')" + assert op[4] == "Start element: u'root' {u'attr1': u'value1', u'attr2': u'value2\\u1f40'}" + assert op[5] == "NS decl: u'myns' u'http://www.python.org/namespace'" + assert op[6] == "Start element: u'http://www.python.org/namespace!subelement' {}" + assert op[7] == "Character data: u'Contents of subelements'" + assert op[8] == "End element: u'http://www.python.org/namespace!subelement'" + assert op[9] == "End of NS decl: u'myns'" + assert op[10] == "Start element: u'sub2' {}" + assert op[11] == 'Start of CDATA section' + assert op[12] == "Character data: u'contents of CDATA section'" + assert op[13] == 'End of CDATA section' + assert op[14] == "End element: u'sub2'" + assert op[15] == "External entity ref: (None, u'entity.file', None)" + assert op[16] == "End element: u'root'" + + +class TestNamespaceSeparator: + def test_legal(self): + # Tests that make sure we get errors when the namespace_separator value + # is illegal, and that we don't for good values: + expat.ParserCreate() + expat.ParserCreate(namespace_separator=None) + expat.ParserCreate(namespace_separator=' ') + + def test_illegal(self): + try: + expat.ParserCreate(namespace_separator=42) + raise AssertionError + except TypeError, e: + assert str(e) == ( + 'ParserCreate() argument 2 must be string or None, not int') + + try: + expat.ParserCreate(namespace_separator='too long') + raise AssertionError + except ValueError, e: + assert str(e) == ( + 'namespace_separator must be at most one character, omitted, or None') + + def test_zero_length(self): + # ParserCreate() needs to accept a namespace_separator of zero length + # to satisfy the requirements of RDF applications that are required + # to simply glue together the namespace URI and the localname. Though + # considered a wart of the RDF specifications, it needs to be supported. + # + # See XML-SIG mailing list thread starting with + # http://mail.python.org/pipermail/xml-sig/2001-April/005202.html + # + expat.ParserCreate(namespace_separator='') # too short + + +class TestInterning: + def test(self): + # Test the interning machinery. + p = expat.ParserCreate() + L = [] + def collector(name, *args): + L.append(name) + p.StartElementHandler = collector + p.EndElementHandler = collector + p.Parse(" ", 1) + tag = L[0] + assert len(L) == 6 + for entry in L: + # L should have the same string repeated over and over. + assert tag is entry + + +class TestBufferText: + def setup_method(self, meth): + self.stuff = [] + self.parser = expat.ParserCreate() + self.parser.buffer_text = 1 + self.parser.CharacterDataHandler = self.CharacterDataHandler + + def check(self, expected, label): + assert self.stuff == expected, ( + "%s\nstuff = %r\nexpected = %r" + % (label, self.stuff, map(unicode, expected))) + + def CharacterDataHandler(self, text): + self.stuff.append(text) + + def StartElementHandler(self, name, attrs): + self.stuff.append("<%s>" % name) + bt = attrs.get("buffer-text") + if bt == "yes": + self.parser.buffer_text = 1 + elif bt == "no": + self.parser.buffer_text = 0 + + def EndElementHandler(self, name): + self.stuff.append("" % name) + + def CommentHandler(self, data): + self.stuff.append("" % data) + + def setHandlers(self, handlers=[]): + for name in handlers: + setattr(self.parser, name, getattr(self, name)) + + def test_default_to_disabled(self): + parser = expat.ParserCreate() + assert not parser.buffer_text + + def test_buffering_enabled(self): + # Make sure buffering is turned on + assert self.parser.buffer_text + self.parser.Parse("123", 1) + assert self.stuff == ['123'], ( + "buffered text not properly collapsed") + + def test1(self): + # XXX This test exposes more detail of Expat's text chunking than we + # XXX like, but it tests what we need to concisely. + self.setHandlers(["StartElementHandler"]) + self.parser.Parse("12\n34\n5", 1) + assert self.stuff == ( + ["", "1", "", "2", "\n", "3", "", "4\n5"]), ( + "buffering control not reacting as expected") + + def test2(self): + self.parser.Parse("1<2> \n 3", 1) + assert self.stuff == ["1<2> \n 3"], ( + "buffered text not properly collapsed") + + def test3(self): + self.setHandlers(["StartElementHandler"]) + self.parser.Parse("123", 1) + assert self.stuff == ["", "1", "", "2", "", "3"], ( + "buffered text not properly split") + + def test4(self): + self.setHandlers(["StartElementHandler", "EndElementHandler"]) + self.parser.CharacterDataHandler = None + self.parser.Parse("123", 1) + assert self.stuff == ( + ["", "", "", "", "", ""]) + + def test5(self): + self.setHandlers(["StartElementHandler", "EndElementHandler"]) + self.parser.Parse("123", 1) + assert self.stuff == ( + ["", "1", "", "", "2", "", "", "3", ""]) + + def test6(self): + self.setHandlers(["CommentHandler", "EndElementHandler", + "StartElementHandler"]) + self.parser.Parse("12345 ", 1) + assert self.stuff == ( + ["", "1", "", "", "2", "", "", "345", ""]), ( + "buffered text not properly split") + + def test7(self): + self.setHandlers(["CommentHandler", "EndElementHandler", + "StartElementHandler"]) + self.parser.Parse("12345 ", 1) + assert self.stuff == ( + ["", "1", "", "", "2", "", "", "3", + "", "4", "", "5", ""]), ( + "buffered text not properly split") + + +# Test handling of exception from callback: +class TestHandlerException: + def StartElementHandler(self, name, attrs): + raise RuntimeError(name) + + def test(self): + parser = expat.ParserCreate() + parser.StartElementHandler = self.StartElementHandler + try: + parser.Parse("", 1) + raise AssertionError + except RuntimeError, e: + assert e.args[0] == 'a', ( + "Expected RuntimeError for element 'a', but" + \ + " found %r" % e.args[0]) + + +# Test Current* members: +class TestPosition: + def StartElementHandler(self, name, attrs): + self.check_pos('s') + + def EndElementHandler(self, name): + self.check_pos('e') + + def check_pos(self, event): + pos = (event, + self.parser.CurrentByteIndex, + self.parser.CurrentLineNumber, + self.parser.CurrentColumnNumber) + assert self.upto < len(self.expected_list) + expected = self.expected_list[self.upto] + assert pos == expected, ( + 'Expected position %s, got position %s' %(pos, expected)) + self.upto += 1 + + def test_x(self): + self.parser = expat.ParserCreate() + self.parser.StartElementHandler = self.StartElementHandler + self.parser.EndElementHandler = self.EndElementHandler + self.upto = 0 + self.expected_list = [('s', 0, 1, 0), ('s', 5, 2, 1), ('s', 11, 3, 2), + ('e', 15, 3, 6), ('e', 17, 4, 1), ('e', 22, 5, 0)] + + xml = '\n \n \n \n' + self.parser.Parse(xml, 1) + + +class Testsf1296433: + def test_parse_only_xml_data(self): + try: + import __pypy__ + except ImportError: + import py + py.test.skip("segfaults cpython") + # http://python.org/sf/1296433 + # + xml = "%s" % ('a' * 1025) + # this one doesn't crash + #xml = "%s" % ('a' * 10000) + + class SpecificException(Exception): + pass + + def handler(text): + raise SpecificException + + parser = expat.ParserCreate() + parser.CharacterDataHandler = handler + + raises(Exception, parser.Parse, xml) + +class TestChardataBuffer: + """ + test setting of chardata buffer size + """ + def setup_class(cls): + import py + py.test.skip("Doesn't work on cpy 2.5") + + def test_1025_bytes(self): + assert self.small_buffer_test(1025) == 2 + + def test_1000_bytes(self): + assert self.small_buffer_test(1000) == 1 + + def test_wrong_size(self): + parser = expat.ParserCreate() + parser.buffer_text = 1 + def f(size): + parser.buffer_size = size + + raises(TypeError, f, sys.maxint+1) + raises(ValueError, f, -1) + raises(ValueError, f, 0) + + def test_unchanged_size(self): + xml1 = ("%s" % ('a' * 512)) + xml2 = 'a'*512 + '' + parser = expat.ParserCreate() + parser.CharacterDataHandler = self.counting_handler + parser.buffer_size = 512 + parser.buffer_text = 1 + + # Feed 512 bytes of character data: the handler should be called + # once. + self.n = 0 + parser.Parse(xml1) + assert self.n == 1 + + # Reassign to buffer_size, but assign the same size. + parser.buffer_size = parser.buffer_size + assert self.n == 1 + + # Try parsing rest of the document + parser.Parse(xml2) + assert self.n == 2 + + + def test_disabling_buffer(self): + xml1 = "%s" % ('a' * 512) + xml2 = ('b' * 1024) + xml3 = "%s" % ('c' * 1024) + parser = expat.ParserCreate() + parser.CharacterDataHandler = self.counting_handler + parser.buffer_text = 1 + parser.buffer_size = 1024 + assert parser.buffer_size == 1024 + + # Parse one chunk of XML + self.n = 0 + parser.Parse(xml1, 0) + assert parser.buffer_size == 1024 + assert self.n == 1 + + # Turn off buffering and parse the next chunk. + parser.buffer_text = 0 + assert not parser.buffer_text + assert parser.buffer_size == 1024 + for i in range(10): + parser.Parse(xml2, 0) + assert self.n == 11 + + parser.buffer_text = 1 + assert parser.buffer_text + assert parser.buffer_size == 1024 + parser.Parse(xml3, 1) + assert self.n == 12 + + + + def make_document(self, bytes): + return ("" + bytes * 'a' + '') + + def counting_handler(self, text): + self.n += 1 + + def small_buffer_test(self, buffer_len): + xml = "%s" % ('a' * buffer_len) + parser = expat.ParserCreate() + parser.CharacterDataHandler = self.counting_handler + parser.buffer_size = 1024 + parser.buffer_text = 1 + + self.n = 0 + parser.Parse(xml) + return self.n + + def test_change_size_1(self): + xml1 = "%s" % ('a' * 1024) + xml2 = "aaa%s" % ('a' * 1025) + parser = expat.ParserCreate() + parser.CharacterDataHandler = self.counting_handler + parser.buffer_text = 1 + parser.buffer_size = 1024 + assert parser.buffer_size == 1024 + + self.n = 0 + parser.Parse(xml1, 0) + parser.buffer_size *= 2 + assert parser.buffer_size == 2048 + parser.Parse(xml2, 1) + assert self.n == 2 + + def test_change_size_2(self): + xml1 = "a%s" % ('a' * 1023) + xml2 = "aaa%s" % ('a' * 1025) + parser = expat.ParserCreate() + parser.CharacterDataHandler = self.counting_handler + parser.buffer_text = 1 + parser.buffer_size = 2048 + assert parser.buffer_size == 2048 + + self.n=0 + parser.Parse(xml1, 0) + parser.buffer_size /= 2 + assert parser.buffer_size == 1024 + parser.Parse(xml2, 1) + assert self.n == 4 From fijal at codespeak.net Tue May 27 01:28:23 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 27 May 2008 01:28:23 +0200 (CEST) Subject: [pypy-svn] r55284 - in pypy/dist/pypy/lib: _ctypes app_test/ctypes_tests Message-ID: <20080526232823.29B92169F44@codespeak.net> Author: fijal Date: Tue May 27 01:28:20 2008 New Revision: 55284 Modified: pypy/dist/pypy/lib/_ctypes/function.py pypy/dist/pypy/lib/app_test/ctypes_tests/test_callback_traceback.py Log: Print tracebacks on error, unskip tests. Modified: pypy/dist/pypy/lib/_ctypes/function.py ============================================================================== --- pypy/dist/pypy/lib/_ctypes/function.py (original) +++ pypy/dist/pypy/lib/_ctypes/function.py Tue May 27 01:28:20 2008 @@ -1,6 +1,8 @@ from _ctypes.basics import _CData, _CDataMeta, ArgumentError, keepalive_key import _rawffi +import sys +import traceback # XXX this file needs huge refactoring I fear @@ -98,7 +100,13 @@ def __call__(self, *args): if self.callable is not None: - res = self.callable(*args) + try: + res = self.callable(*args) + except: + exc_info = sys.exc_info() + traceback.print_tb(exc_info[2], file=sys.stderr) + print >>sys.stderr, "%s: %s" % (exc_info[0].__name__, exc_info[1]) + return 0 if self._restype_ is not None: return res return Modified: pypy/dist/pypy/lib/app_test/ctypes_tests/test_callback_traceback.py ============================================================================== --- pypy/dist/pypy/lib/app_test/ctypes_tests/test_callback_traceback.py (original) +++ pypy/dist/pypy/lib/app_test/ctypes_tests/test_callback_traceback.py Tue May 27 01:28:20 2008 @@ -7,8 +7,6 @@ 42 / arg raise ValueError, arg -py.test.skip("implementation details are different on pypy") - class TestCallbackTraceback: # When an exception is raised in a ctypes callback function, the C # code prints a traceback. @@ -53,7 +51,7 @@ def test_TypeErrorDivisionError(self): cb = CFUNCTYPE(c_int, c_char_p)(callback_func) out = self.capture_stderr(cb, "spam") - assert out.splitlines()[-1] == ( + assert out.splitlines()[-1].startswith( "TypeError: " - "unsupported operand type(s) for /: 'int' and 'str'") + "unsupported operand type(s) for") From santagada at codespeak.net Tue May 27 02:46:30 2008 From: santagada at codespeak.net (santagada at codespeak.net) Date: Tue, 27 May 2008 02:46:30 +0200 (CEST) Subject: [pypy-svn] r55285 - in pypy/branch/js-refactoring/pypy/lang/js: . test test/ecma Message-ID: <20080527004630.C31EE2A809F@codespeak.net> Author: santagada Date: Tue May 27 02:46:27 2008 New Revision: 55285 Modified: pypy/branch/js-refactoring/pypy/lang/js/baseop.py pypy/branch/js-refactoring/pypy/lang/js/interpreter.py pypy/branch/js-refactoring/pypy/lang/js/js_interactive.py pypy/branch/js-refactoring/pypy/lang/js/jscode.py pypy/branch/js-refactoring/pypy/lang/js/jsobj.py pypy/branch/js-refactoring/pypy/lang/js/test/ecma/conftest.py pypy/branch/js-refactoring/pypy/lang/js/test/test_interp.py Log: new array.Put method, some more To... receive the context, new reporting, and a huge bug about primitive objects not having propdicts. probably they also need the funcions from their object conterparts Modified: pypy/branch/js-refactoring/pypy/lang/js/baseop.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/baseop.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/baseop.py Tue May 27 02:46:27 2008 @@ -34,8 +34,8 @@ def sub(ctx, nleft, nright): if isinstance(nleft, W_IntNumber) and isinstance(nright, W_IntNumber): - ileft = nleft.ToInt32() - iright = nright.ToInt32() + ileft = nleft.ToInt32(ctx) + iright = nright.ToInt32(ctx) try: return W_IntNumber(ovfcheck(ileft - iright)) except OverflowError: @@ -46,8 +46,8 @@ def mult(ctx, nleft, nright): if isinstance(nleft, W_IntNumber) and isinstance(nright, W_IntNumber): - ileft = nleft.ToInt32() - iright = nright.ToInt32() + ileft = nleft.ToInt32(ctx) + iright = nright.ToInt32(ctx) try: return W_IntNumber(ovfcheck(ileft * iright)) except OverflowError: @@ -57,9 +57,9 @@ return W_FloatNumber(fleft * fright) def mod(ctx, nleft, nright): # XXX this one is really not following spec - ileft = nleft.ToInt32() - iright = nright.ToInt32() - return W_IntNumber(ileft % iright) + fleft = nleft.ToNumber(ctx) + fright = nright.ToNumber(ctx) + return W_FloatNumber(fleft % fright) def division(ctx, nleft, nright): # XXX optimise for ints and floats Modified: pypy/branch/js-refactoring/pypy/lang/js/interpreter.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/interpreter.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/interpreter.py Tue May 27 02:46:27 2008 @@ -94,10 +94,10 @@ class W_ArrayObject(W_NativeObject): def Call(self, ctx, args=[], this=None): - proto = ctx.get_global().Get('Array').Get('prototype') + proto = ctx.get_global().Get(ctx, 'Array').Get(ctx, 'prototype') array = W_Array(ctx, Prototype=proto, Class = proto.Class) for i in range(len(args)): - array.Put(str(i), args[i]) + array.Put(ctx, str(i), args[i]) return array def Construct(self, ctx, args=[]): @@ -127,7 +127,7 @@ return W_FloatNumber(NAN) s = args[0].ToString(ctx).strip(" ") if len(args) > 1: - radix = args[1].ToInt32() + radix = args[1].ToInt32(ctx) else: radix = 10 if len(s) >= 2 and (s.startswith('0x') or s.startswith('0X')) : @@ -324,7 +324,7 @@ def Call(self, ctx, args=[], this=None): string = this.ToString(ctx) if len(args)>=1: - pos = args[0].ToInt32() + pos = args[0].ToInt32(ctx) if (not pos >=0) or (pos > len(string) - 1): return W_String('') else: @@ -349,7 +349,7 @@ if len(args) < 2: pos = 0 else: - pos = args[1].ToInt32() + pos = args[1].ToInt32(ctx) pos = min(max(pos, 0), size) return W_IntNumber(string.find(substr, pos)) @@ -360,11 +360,11 @@ if len(args) < 1: start = 0 else: - start = args[0].ToInt32() + start = args[0].ToInt32(ctx) if len(args) < 2: end = size else: - end = args[1].ToInt32() + end = args[1].ToInt32(ctx) tmp1 = min(max(start, 0), size) tmp2 = min(max(end, 0), size) start = min(tmp1, tmp2) @@ -373,9 +373,9 @@ class W_ArrayToString(W_NewBuiltin): def Call(self, ctx, args=[], this=None): - length = this.Get('length').ToUInt32() + length = this.Get(ctx, 'length').ToUInt32(ctx) sep = ',' - return W_String(sep.join([this.Get(str(index)).ToString(ctx) + return W_String(sep.join([this.Get(ctx, str(index)).ToString(ctx) for index in range(length)])) class W_DateFake(W_NewBuiltin): # XXX This is temporary @@ -393,7 +393,7 @@ def __init__(self): def put_values(obj, dictvalues): for key,value in dictvalues.iteritems(): - obj.Put(key, value) + obj.Put(ctx, key, value) w_Global = W_Object(Class="global") @@ -404,17 +404,17 @@ w_Function = W_Function(ctx, Class='Function', Prototype=w_ObjPrototype) - w_Global.Put('Function', w_Function) + w_Global.Put(ctx, 'Function', w_Function) w_Object = W_ObjectObject('Object', w_Function) - w_Object.Put('prototype', w_ObjPrototype, dd=True, de=True, ro=True) + w_Object.Put(ctx, 'prototype', w_ObjPrototype, dd=True, de=True, ro=True) - w_Global.Put('Object', w_Object) + w_Global.Put(ctx, 'Object', w_Object) w_FncPrototype = w_Function.Call(ctx, this=w_Function) - w_Function.Put('prototype', w_FncPrototype, dd=True, de=True, ro=True) - w_Function.Put('constructor', w_Function) + w_Function.Put(ctx, 'prototype', w_FncPrototype, dd=True, de=True, ro=True) + w_Function.Put(ctx, 'constructor', w_Function) - w_Object.Put('length', W_IntNumber(1), ro=True, dd=True) + w_Object.Put(ctx, 'length', W_IntNumber(1), ro=True, dd=True) toString = W_ToString(ctx) @@ -439,8 +439,8 @@ }) w_Boolean = W_BooleanObject('Boolean', w_FncPrototype) - w_Boolean.Put('constructor', w_FncPrototype, dd=True, ro=True, de=True) - w_Boolean.Put('length', W_IntNumber(1), dd=True, ro=True, de=True) + w_Boolean.Put(ctx, 'constructor', w_FncPrototype, dd=True, ro=True, de=True) + w_Boolean.Put(ctx, 'length', W_IntNumber(1), dd=True, ro=True, de=True) w_BoolPrototype = create_object(ctx, 'Object', Value=W_Boolean(False)) w_BoolPrototype.Class = 'Boolean' @@ -452,9 +452,9 @@ 'valueOf': get_value_of('Boolean', ctx), }) - w_Boolean.Put('prototype', w_BoolPrototype, dd=True, ro=True, de=True) + w_Boolean.Put(ctx, 'prototype', w_BoolPrototype, dd=True, ro=True, de=True) - w_Global.Put('Boolean', w_Boolean) + w_Global.Put(ctx, 'Boolean', w_Boolean) #Number w_Number = W_NumberObject('Number', w_FncPrototype) @@ -477,18 +477,18 @@ 'length' : W_IntNumber(1), }) w_Number.propdict['prototype'].ro = True - w_Number.Put('MAX_VALUE', W_FloatNumber(1.7976931348623157e308), + w_Number.Put(ctx, 'MAX_VALUE', W_FloatNumber(1.7976931348623157e308), ro=True, dd=True) - w_Number.Put('MIN_VALUE', W_FloatNumber(0), ro=True, dd=True) - w_Number.Put('NaN', W_FloatNumber(NAN), ro=True, dd=True) + w_Number.Put(ctx, 'MIN_VALUE', W_FloatNumber(0), ro=True, dd=True) + w_Number.Put(ctx, 'NaN', W_FloatNumber(NAN), ro=True, dd=True) # ^^^ this is exactly in test case suite - w_Number.Put('POSITIVE_INFINITY', W_FloatNumber(INFINITY), + w_Number.Put(ctx, 'POSITIVE_INFINITY', W_FloatNumber(INFINITY), ro=True, dd=True) - w_Number.Put('NEGATIVE_INFINITY', W_FloatNumber(-INFINITY), + w_Number.Put(ctx, 'NEGATIVE_INFINITY', W_FloatNumber(-INFINITY), ro=True, dd=True) - w_Global.Put('Number', w_Number) + w_Global.Put(ctx, 'Number', w_Number) #String @@ -508,8 +508,8 @@ 'substring': W_Substring(ctx), }) - w_String.Put('prototype', w_StrPrototype) - w_Global.Put('String', w_String) + w_String.Put(ctx, 'prototype', w_StrPrototype) + w_Global.Put(ctx, 'String', w_String) w_Array = W_ArrayObject('Array', w_FncPrototype) @@ -522,43 +522,43 @@ 'toString': W_ArrayToString(ctx), }) - w_Array.Put('prototype', w_ArrPrototype) - w_Global.Put('Array', w_Array) + w_Array.Put(ctx, 'prototype', w_ArrPrototype) + w_Global.Put(ctx, 'Array', w_Array) #Math w_math = W_Object(Class='Math') - w_Global.Put('Math', w_math) - w_math.Put('__proto__', w_ObjPrototype) - w_math.Put('prototype', w_ObjPrototype, dd=True, de=True, ro=True) - w_math.Put('abs', W_Builtin(absjs, Class='function')) - w_math.Put('floor', W_Builtin(floorjs, Class='function')) - w_math.Put('pow', W_Builtin(powjs, Class='function')) - w_math.Put('sqrt', W_Builtin(sqrtjs, Class='function')) - w_math.Put('E', W_FloatNumber(math.e)) - w_math.Put('PI', W_FloatNumber(math.pi)) + w_Global.Put(ctx, 'Math', w_math) + w_math.Put(ctx, '__proto__', w_ObjPrototype) + w_math.Put(ctx, 'prototype', w_ObjPrototype, dd=True, de=True, ro=True) + w_math.Put(ctx, 'abs', W_Builtin(absjs, Class='function')) + w_math.Put(ctx, 'floor', W_Builtin(floorjs, Class='function')) + w_math.Put(ctx, 'pow', W_Builtin(powjs, Class='function')) + w_math.Put(ctx, 'sqrt', W_Builtin(sqrtjs, Class='function')) + w_math.Put(ctx, 'E', W_FloatNumber(math.e)) + w_math.Put(ctx, 'PI', W_FloatNumber(math.pi)) - w_Global.Put('version', W_Builtin(versionjs)) + w_Global.Put(ctx, 'version', W_Builtin(versionjs)) #Date w_Date = W_DateFake(ctx, Class='Date') - w_Global.Put('Date', w_Date) + w_Global.Put(ctx, 'Date', w_Date) - w_Global.Put('NaN', W_FloatNumber(NAN)) - w_Global.Put('Infinity', W_FloatNumber(INFINITY)) - w_Global.Put('undefined', w_Undefined) - w_Global.Put('eval', W_Builtin(evaljs)) - w_Global.Put('parseInt', W_Builtin(parseIntjs)) - w_Global.Put('parseFloat', W_Builtin(parseFloatjs)) - w_Global.Put('isNaN', W_Builtin(isnanjs)) - w_Global.Put('isFinite', W_Builtin(isfinitejs)) + w_Global.Put(ctx, 'NaN', W_FloatNumber(NAN)) + w_Global.Put(ctx, 'Infinity', W_FloatNumber(INFINITY)) + w_Global.Put(ctx, 'undefined', w_Undefined) + w_Global.Put(ctx, 'eval', W_Builtin(evaljs)) + w_Global.Put(ctx, 'parseInt', W_Builtin(parseIntjs)) + w_Global.Put(ctx, 'parseFloat', W_Builtin(parseFloatjs)) + w_Global.Put(ctx, 'isNaN', W_Builtin(isnanjs)) + w_Global.Put(ctx, 'isFinite', W_Builtin(isfinitejs)) - w_Global.Put('print', W_Builtin(printjs)) - w_Global.Put('this', w_Global) + w_Global.Put(ctx, 'print', W_Builtin(printjs)) + w_Global.Put(ctx, 'this', w_Global) # DEBUGGING if 0: - w_Global.Put('pypy_repr', W_Builtin(pypy_repr)) + w_Global.Put(ctx, 'pypy_repr', W_Builtin(pypy_repr)) self.global_context = ctx self.w_Global = w_Global Modified: pypy/branch/js-refactoring/pypy/lang/js/js_interactive.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/js_interactive.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/js_interactive.py Tue May 27 02:46:27 2008 @@ -49,9 +49,10 @@ def __init__(self, locals=None, filename=""): code.InteractiveConsole.__init__(self, locals, filename) self.interpreter = Interpreter() - self.interpreter.w_Global.Put('quit', W_Builtin(quitjs)) - self.interpreter.w_Global.Put('load', W_Builtin(loadjs)) - self.interpreter.w_Global.Put('trace', W_Builtin(tracejs)) + ctx = self.interpreter.global_context + self.interpreter.w_Global.Put(ctx, 'quit', W_Builtin(quitjs)) + self.interpreter.w_Global.Put(ctx, 'load', W_Builtin(loadjs)) + self.interpreter.w_Global.Put(ctx, 'trace', W_Builtin(tracejs)) def runcodefromfile(self, filename): Modified: pypy/branch/js-refactoring/pypy/lang/js/jscode.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/jscode.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/jscode.py Tue May 27 02:46:27 2008 @@ -201,8 +201,8 @@ class BaseBinaryBitwiseOp(Opcode): def eval(self, ctx, stack): - s5 = stack.pop().ToInt32() - s6 = stack.pop().ToInt32() + s5 = stack.pop().ToInt32(ctx) + s6 = stack.pop().ToInt32(ctx) stack.append(self.operation(ctx, s5, s6)) def operation(self, ctx, op1, op2): @@ -287,7 +287,7 @@ def eval(self, ctx, stack): xxx scope = ctx.scope[self.depth] - stack.append(scope.Get(self.identifier)) + stack.append(scope.Get(ctx, self.identifier)) #stack.append(W_Reference(self.identifier, scope)) def __repr__(self): @@ -298,10 +298,10 @@ self.counter = counter def eval(self, ctx, stack): - proto = ctx.get_global().Get('Array').Get('prototype') + proto = ctx.get_global().Get(ctx, 'Array').Get(ctx, 'prototype') array = W_Array(ctx, Prototype=proto, Class = proto.Class) for i in range(self.counter): - array.Put(str(self.counter - i - 1), stack.pop()) + array.Put(ctx, str(self.counter - i - 1), stack.pop()) stack.append(array) def __repr__(self): @@ -325,13 +325,13 @@ self.funcobj = funcobj def eval(self, ctx, stack): - proto = ctx.get_global().Get('Function').Get('prototype') + proto = ctx.get_global().Get(ctx, 'Function').Get(ctx, 'prototype') w_func = W_Object(ctx=ctx, Prototype=proto, Class='Function', callfunc=self.funcobj) - w_func.Put('length', W_IntNumber(len(self.funcobj.params))) + w_func.Put(ctx, 'length', W_IntNumber(len(self.funcobj.params))) w_obj = create_object(ctx, 'Object') - w_obj.Put('constructor', w_func, de=True) - w_func.Put('prototype', w_obj) + w_obj.Put(ctx, 'constructor', w_func, de=True) + w_func.Put(ctx, 'prototype', w_obj) stack.append(w_func) def __repr__(self): @@ -344,7 +344,7 @@ # def eval(self, ctx, stack): # value = stack[-1] -# ctx.scope[self.depth].Put(self.name, value) +# ctx.scope[self.depth].Put(ctx, self.name, value) # def __repr__(self): # return 'STORE_VAR "%s"' % self.name @@ -358,7 +358,7 @@ for _ in range(self.counter): name = stack.pop().ToString(ctx) w_elem = stack.pop() - w_obj.Put(name, w_elem) + w_obj.Put(ctx, name, w_elem) stack.append(w_obj) def __repr__(self): @@ -370,7 +370,7 @@ def eval(self, ctx, stack): w_obj = stack.pop().ToObject(ctx) - stack.append(w_obj.Get(self.name)) + stack.append(w_obj.Get(ctx, self.name)) #stack.append(W_Reference(self.name, w_obj)) def __repr__(self): @@ -380,7 +380,7 @@ def eval(self, ctx, stack): name = stack.pop().ToString(ctx) w_obj = stack.pop().ToObject(ctx) - stack.append(w_obj.Get(name)) + stack.append(w_obj.Get(ctx, name)) #stack.append(W_Reference(name, w_obj)) class COMMA(BaseUnaryOperation): @@ -449,20 +449,20 @@ class URSH(BaseBinaryBitwiseOp): def eval(self, ctx, stack): - op2 = stack.pop().ToUInt32() - op1 = stack.pop().ToUInt32() + op2 = stack.pop().ToUInt32(ctx) + op1 = stack.pop().ToUInt32(ctx) stack.append(W_IntNumber(op1 >> (op2 & 0x1F))) class RSH(BaseBinaryBitwiseOp): def eval(self, ctx, stack): - op2 = stack.pop().ToUInt32() - op1 = stack.pop().ToInt32() + op2 = stack.pop().ToUInt32(ctx) + op1 = stack.pop().ToInt32(ctx) stack.append(W_IntNumber(op1 >> intmask(op2 & 0x1F))) class LSH(BaseBinaryBitwiseOp): def eval(self, ctx, stack): - op2 = stack.pop().ToUInt32() - op1 = stack.pop().ToInt32() + op2 = stack.pop().ToUInt32(ctx) + op1 = stack.pop().ToInt32(ctx) stack.append(W_IntNumber(op1 << intmask(op2 & 0x1F))) class MUL(BaseBinaryOperation): @@ -542,7 +542,7 @@ value = stack.pop() name = elem.ToString() value = self.operation(ctx, left, name, value) - left.Put(name, value) + left.Put(ctx, name, value) stack.append(value) class STORE_MEMBER(BaseStoreMember): @@ -551,7 +551,7 @@ class BaseStoreMemberAssign(BaseStoreMember): def operation(self, ctx, left, name, value): - prev = left.Get(name) + prev = left.Get(ctx, name) return self.decision(ctx, value, prev) class STORE_MEMBER_ADD(BaseStoreMemberAssign): @@ -594,8 +594,8 @@ class BaseAssignBitOper(BaseStore): def process(self, ctx, name, stack): - right = stack.pop().ToInt32() - left = ctx.resolve_identifier(name).ToInt32() + right = stack.pop().ToInt32(ctx) + left = ctx.resolve_identifier(name).ToInt32(ctx) result = self.operation(ctx, left, right) stack.append(result) return result @@ -705,14 +705,14 @@ def eval(self, ctx, stack): # function declaration actyally don't run anything - proto = ctx.get_global().Get('Function').Get('prototype') + proto = ctx.get_global().Get(ctx, 'Function').Get(ctx, 'prototype') w_func = W_Object(ctx=ctx, Prototype=proto, Class='Function', callfunc=self.funcobj) - w_func.Put('length', W_IntNumber(len(self.funcobj.params))) + w_func.Put(ctx, 'length', W_IntNumber(len(self.funcobj.params))) w_obj = create_object(ctx, 'Object') - w_obj.Put('constructor', w_func, de=True) - w_func.Put('prototype', w_obj) + w_obj.Put(ctx, 'constructor', w_func, de=True) + w_func.Put(ctx, 'prototype', w_obj) if self.funcobj.name is not None: - ctx.put(self.funcobj.name, w_func) + ctx.Put(ctx, self.funcobj.name, w_func) def __repr__(self): funcobj = self.funcobj @@ -728,7 +728,7 @@ self.name = name def eval(self, ctx, stack): - ctx.put(self.name, w_Undefined, dd=True) + ctx.Put(ctx, self.name, w_Undefined, dd=True) def __repr__(self): return 'DECLARE_VAR "%s"' % (self.name,) @@ -758,7 +758,7 @@ method = stack.pop() what = stack.pop().ToObject(ctx) args = stack.pop() - r1 = what.Get(method.ToString()) + r1 = what.Get(ctx, method.ToString()) if not isinstance(r1, W_PrimitiveObject): raise ThrowException(W_String("it is not a callable")) try: @@ -792,7 +792,7 @@ if self.catchcode is not None: # XXX just copied, I don't know if it's right obj = W_Object() - obj.Put(self.catchparam, e.exception) + obj.Put(ctx, self.catchparam, e.exception) ctx.push_object(obj) try: self.catchcode.run(ctx) Modified: pypy/branch/js-refactoring/pypy/lang/js/jsobj.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/jsobj.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/jsobj.py Tue May 27 02:46:27 2008 @@ -29,7 +29,7 @@ #def GetValue(self): # return self - def ToBoolean(self): + def ToBoolean(self, ctx): raise NotImplementedError() def ToPrimitive(self, ctx, hint=""): @@ -45,24 +45,24 @@ def ToNumber(self, ctx): return 0.0 - def ToInt32(self): + def ToInt32(self, ctx): return int(self.ToNumber(ctx)) - def ToUInt32(self): + def ToUInt32(self, ctx): return r_uint(0) - def Get(self, P): - raise NotImplementedError + def Get(self, ctx, P): + raise NotImplementedError() - def Put(self, P, V, dd=False, + def Put(self, ctx, P, V, dd=False, ro=False, de=False, it=False): - pass + raise NotImplementedError() def PutValue(self, w, ctx): pass def Call(self, ctx, args=[], this=None): - raise NotImplementedError + raise NotImplementedError() def __str__(self): return self.ToString(ctx=None) @@ -106,11 +106,6 @@ w_Null = W_Null() -class W_Primitive(W_Root): - """unifying parent for primitives""" - def ToPrimitive(self, ctx, hint=""): - return self - class W_PrimitiveObject(W_Root): def __init__(self, ctx=None, Prototype=None, Class='Object', Value=w_Undefined, callfunc=None): @@ -139,35 +134,35 @@ value = args[i] except IndexError: value = w_Undefined - act.Put(paramname, value) - act.Put('this', this) + act.Put(ctx, paramname, value) + act.Put(ctx, 'this', this) w_Arguments = W_Arguments(self, args) - act.Put('arguments', w_Arguments) + act.Put(ctx, 'arguments', w_Arguments) newctx = function_context(self.Scope, act, this) val = self.callfunc.run(ctx=newctx) return val def Construct(self, ctx, args=[]): obj = W_Object(Class='Object') - prot = self.Get('prototype') + prot = self.Get(ctx, 'prototype') if isinstance(prot, W_PrimitiveObject): obj.Prototype = prot else: # would love to test this #but I fail to find a case that falls into this - obj.Prototype = ctx.get_global().Get('Object').Get('prototype') + obj.Prototype = ctx.get_global().Get(ctx, 'Object').Get(ctx, 'prototype') try: #this is a hack to be compatible to spidermonkey self.Call(ctx, args, this=obj) return obj except ReturnException, e: return e.value - def Get(self, P): + def Get(self, ctx, P): try: return self.propdict[P].value except KeyError: if self.Prototype is None: return w_Undefined - return self.Prototype.Get(P) # go down the prototype chain + return self.Prototype.Get(ctx, P) # go down the prototype chain def CanPut(self, P): if P in self.propdict: @@ -176,7 +171,7 @@ if self.Prototype is None: return True return self.Prototype.CanPut(P) - def Put(self, P, V, dd=False, + def Put(self, ctx, P, V, dd=False, ro=False, de=False, it=False): try: P = self.propdict[P] @@ -200,12 +195,12 @@ return True def internal_def_value(self, ctx, tryone, trytwo): - t1 = self.Get(tryone) + t1 = self.Get(ctx, tryone) if isinstance(t1, W_PrimitiveObject): val = t1.Call(ctx, this=self) if isinstance(val, W_Primitive): return val - t2 = self.Get(trytwo) + t2 = self.Get(ctx, trytwo) if isinstance(t2, W_PrimitiveObject): val = t2.Call(ctx, this=self) if isinstance(val, W_Primitive): @@ -238,6 +233,12 @@ return 'function' else: return 'object' + + +class W_Primitive(W_PrimitiveObject): + """unifying parent for primitives""" + def ToPrimitive(self, ctx, hint=""): + return self def str_builtin(ctx, args, this): return W_String(this.ToString(ctx)) @@ -249,13 +250,13 @@ Class, Value, callfunc) def ToNumber(self, ctx): - return self.Get('valueOf').Call(ctx, args=[], this=self).ToNumber(ctx) + return self.Get(ctx, 'valueOf').Call(ctx, args=[], this=self).ToNumber(ctx) class W_NewBuiltin(W_PrimitiveObject): def __init__(self, ctx, Prototype=None, Class='function', Value=w_Undefined, callfunc=None): if Prototype is None: - proto = ctx.get_global().Get('Function').Get('prototype') + proto = ctx.get_global().Get(ctx, 'Function').Get(ctx, 'prototype') Prototype = proto W_PrimitiveObject.__init__(self, ctx, Prototype, Class, Value, callfunc) @@ -295,10 +296,11 @@ def __init__(self, callee, args): W_PrimitiveObject.__init__(self, Class='Arguments') del self.propdict["prototype"] - self.Put('callee', callee) - self.Put('length', W_IntNumber(len(args))) + # XXX None can be dangerous here + self.Put(None, 'callee', callee) + self.Put(None, 'length', W_IntNumber(len(args))) for i in range(len(args)): - self.Put(str(i), args[i]) + self.Put(None, str(i), args[i]) self.length = len(args) class ActivationObject(W_PrimitiveObject): @@ -314,44 +316,52 @@ def __init__(self, ctx=None, Prototype=None, Class='Array', Value=w_Undefined, callfunc=None): W_PrimitiveObject.__init__(self, ctx, Prototype, Class, Value, callfunc) - self.Put('length', W_IntNumber(0)) + self.Put(ctx, 'length', W_IntNumber(0)) self.length = r_uint(0) - def Put(self, P, V, dd=False, - ro=False, de=False, it=False): + def set_length(self, newlength): + if newlength < self.length: + i = newlength + while i < self.length: + key = str(i) + if key in self.propdict: + del self.propdict[key] + i += 1 + self.length = newlength + self.propdict['length'].value = W_FloatNumber(newlength) + + def Put(self, ctx, P, V, dd=False, + ro=False, de=False, it=False): if not self.CanPut(P): return - if P in self.propdict: - if P == 'length': - try: - res = V.ToUInt32() - if V.ToNumber(ctx) < 0: - raise RangeError() - self.propdict['length'].value = W_IntNumber(res) - self.length = res - return - except ValueError: - raise RangeError('invalid array length') - else: - self.propdict[P].value = V + if not P in self.propdict: + self.propdict[P] = Property(P, V, dd = dd, ro = ro, de = de, it = it) else: - self.propdict[P] = Property(P, V, - dd = dd, ro = ro, it = it) - + if P != 'length': + self.propdict[P].value = V + else: + length = V.ToUInt32(ctx) + if length != V.ToNumber(ctx): + raise RangeError() + + self.set_length(length) + return + try: - index = r_uint(int(P)) + arrayindex = r_uint(float(P)) except ValueError: return - if index < self.length: - return - self.length = index+1 - self.propdict['length'].value = W_IntNumber(index+1) - return - + if (arrayindex < self.length) or (arrayindex != float(P)): + return + else: + if (arrayindex + 1) == 0: + raise RangeError() + self.set_length(arrayindex+1) class W_Boolean(W_Primitive): def __init__(self, boolval): + super(W_Primitive, self).__init__() self.boolval = bool(boolval) def ToObject(self, ctx): @@ -378,6 +388,7 @@ class W_String(W_Primitive): def __init__(self, strval): + super(W_Primitive, self).__init__() self.strval = strval def __repr__(self): @@ -416,7 +427,7 @@ def ToObject(self, ctx): return create_object(ctx, 'Number', Value=self) - def Get(self, name): + def Get(self, ctx, name): return w_Undefined def type(self): @@ -426,6 +437,7 @@ """ Number known to be an integer """ def __init__(self, intval): + super(W_Primitive, self).__init__() self.intval = intmask(intval) def ToString(self, ctx=None): @@ -439,10 +451,10 @@ # XXX return float(self.intval) - def ToInt32(self): + def ToInt32(self, ctx): return self.intval - def ToUInt32(self): + def ToUInt32(self, ctx): return r_uint(self.intval) def GetPropertyName(self): @@ -455,7 +467,8 @@ """ Number known to be a float """ def __init__(self, floatval): - self.floatval = floatval + super(W_Primitive, self).__init__() + self.floatval = float(floatval) def ToString(self, ctx = None): # XXX incomplete, this doesn't follow the 9.8.1 recommendation @@ -479,12 +492,12 @@ def ToNumber(self, ctx): return self.floatval - def ToInt32(self): + def ToInt32(self, ctx): if isnan(self.floatval) or isinf(self.floatval): return 0 return intmask(self.floatval) - def ToUInt32(self): + def ToUInt32(self, ctx): if isnan(self.floatval) or isinf(self.floatval): return r_uint(0) return r_uint(self.floatval) @@ -547,7 +560,7 @@ except KeyError: pass # if not, we need to put this thing in current scope - self.variable.Put(name, value) + self.variable.Put(self.get_global(), name, value) def delete_identifier(self, name): for obj in self.scope: @@ -562,9 +575,9 @@ pass return False - def put(self, name, value, dd=False): + def Put(self, ctx, name, value, dd=False): assert name is not None - self.variable.Put(name, value, dd=dd) + self.variable.Put(ctx, name, value, dd=dd) def get_global(self): return self.scope[-1] @@ -632,7 +645,7 @@ return len(self.elements_w) == 0 def create_object(ctx, prototypename, callfunc=None, Value=w_Undefined): - proto = ctx.get_global().Get(prototypename).Get('prototype') + proto = ctx.get_global().Get(ctx, prototypename).Get(ctx, 'prototype') obj = W_Object(ctx, callfunc = callfunc,Prototype=proto, Class = proto.Class, Value = Value) return obj Modified: pypy/branch/js-refactoring/pypy/lang/js/test/ecma/conftest.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/test/ecma/conftest.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/test/ecma/conftest.py Tue May 27 02:46:27 2008 @@ -47,7 +47,7 @@ cls.testcases = cls.interp.global_context.resolve_identifier('testcases') cls.tc = cls.interp.global_context.resolve_identifier('tc') # override eval - cls.interp.global_context.put('eval', W_Builtin(overriden_evaljs)) + cls.interp.w_Global.Put(cls.interp.global_context, 'eval', W_Builtin(overriden_evaljs)) init_interp = classmethod(init_interp) @@ -72,9 +72,10 @@ raise Failed(msg="Javascript Error", excinfo=py.code.ExceptionInfo()) except: raise Failed(excinfo=py.code.ExceptionInfo()) - testcases = self.interp.global_context.resolve_identifier('testcases') - self.tc = self.interp.global_context.resolve_identifier('tc') - testcount = testcases.Get('length').ToInt32() + ctx = self.interp.global_context + testcases = ctx.resolve_identifier('testcases') + self.tc = ctx.resolve_identifier('tc') + testcount = testcases.Get(ctx, 'length').ToInt32(ctx) self.testcases = testcases return range(testcount) Modified: pypy/branch/js-refactoring/pypy/lang/js/test/test_interp.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/test/test_interp.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/test/test_interp.py Tue May 27 02:46:27 2008 @@ -45,11 +45,11 @@ elif isinstance(value, bool): assert code_val.ToBoolean() == value elif isinstance(value, int): - assert code_val.ToInt32() == value + assert code_val.ToInt32(jsint.global_context) == value elif isinstance(value, float): - assert code_val.ToNumber(None) == value + assert code_val.ToNumber(jsint.global_context) == value else: - assert code_val.ToString(ctx) == value + assert code_val.ToString(jsint.global_context) == value def asserte(code, value): jsint = interpreter.Interpreter() From fijal at codespeak.net Tue May 27 03:46:22 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 27 May 2008 03:46:22 +0200 (CEST) Subject: [pypy-svn] r55286 - pypy/dist/pypy/lib Message-ID: <20080527014622.411342D8002@codespeak.net> Author: fijal Date: Tue May 27 03:46:18 2008 New Revision: 55286 Added: pypy/dist/pypy/lib/pyexpat.py (contents, props changed) Log: Working version of pyexpat. Passes all but two tests, but we cannot yet run it on top of pypy, due to some problems with exceptions. Added: pypy/dist/pypy/lib/pyexpat.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/lib/pyexpat.py Tue May 27 03:46:18 2008 @@ -0,0 +1,274 @@ + +import ctypes +import ctypes.util +from ctypes_configure import configure +from ctypes import c_char_p, c_int, c_void_p, POINTER, c_char + +lib = ctypes.CDLL(ctypes.util.find_library('expat')) + +class CConfigure: + _compilation_info_ = configure.ExternalCompilationInfo( + includes = ['expat.h'], + libraries = ['expat'], + pre_include_lines = [ + '#define XML_COMBINED_VERSION (10000*XML_MAJOR_VERSION+100*XML_MINOR_VERSION+XML_MICRO_VERSION)'], + ) + + XML_Char = configure.SimpleType('XML_Char', ctypes.c_char) + XML_COMBINED_VERSION = configure.ConstantInteger('XML_COMBINED_VERSION') + +info = configure.configure(CConfigure) +XML_Char = info['XML_Char'] +XML_COMBINED_VERSION = info['XML_COMBINED_VERSION'] +XML_Parser = ctypes.c_void_p # an opaque pointer +assert XML_Char is ctypes.c_char # this assumption is everywhere in +# cpython's expat, let's explode +XML_ParserCreate = lib.XML_ParserCreate +XML_ParserCreate.args = [ctypes.c_char_p] +XML_ParserCreate.result = XML_Parser +XML_ParserCreateNS = lib.XML_ParserCreateNS +XML_ParserCreateNS.args = [c_char_p, c_char] +XML_ParserCreateNS.result = XML_Parser +XML_Parse = lib.XML_Parse +XML_Parse.args = [XML_Parser, ctypes.c_char_p, ctypes.c_int, ctypes.c_int] +XML_Parse.result = ctypes.c_int + +handler_names = [ + 'StartElement', + 'EndElement', + 'ProcessingInstruction', + 'CharacterData', + 'UnparsedEntityDecl', + 'NotationDecl', + 'StartNamespaceDecl', + 'EndNamespaceDecl', + 'Comment', + 'StartCdataSection', + 'EndCdataSection', + 'Default', + 'DefaultHandlerExpand', + 'NotStandalone', + 'ExternalEntityRef', + 'StartDoctypeDecl', + 'EndDoctypeDecl', + 'EntityDecl', + 'XmlDecl', + 'ElementDecl', + 'AttlistDecl', + ] +if XML_COMBINED_VERSION >= 19504: + handler_names.append('SkippedEntity') +setters = {} + +for name in handler_names: + if name == 'DefaultHandlerExpand': + newname = 'XML_SetDefaultHandlerExpand' + else: + name += 'Handler' + newname = 'XML_Set' + name + cfunc = getattr(lib, newname) + cfunc.args = [XML_Parser, ctypes.c_void_p] + cfunc.result = ctypes.c_int + setters[name] = cfunc + +class ExpatError(Exception): + pass + +error = ExpatError + +class XMLParserType(object): + specified_attributes = 0 + ordered_attributes = 0 + returns_unicode = 1 + encoding = 'utf-8' + def __init__(self, encoding, namespace_separator): + self.returns_unicode = 1 + if encoding: + self.encoding = encoding + if namespace_separator is None: + self.itself = XML_ParserCreate(encoding) + else: + self.itself = XML_ParserCreateNS(encoding, ord(namespace_separator)) + if not self.itself: + raise RuntimeError("Creating parser failed") + self.storage = {} + self.buffer = None + self.buffer_size = 8192 + self.character_data_handler = None + + def _flush_character_buffer(self): + if not self.buffer: + return + res = self._call_character_handler(''.join(self.buffer)) + self.buffer = [] + return res + + def _call_character_handler(self, buf): + if self.character_data_handler: + self.character_data_handler(buf) + + def Parse(self, data, is_final): + res = XML_Parse(self.itself, data, len(data), is_final) + if res == 0: + xxx + self._flush_character_buffer() + return res + + def _sethandler(self, name, real_cb): + setter = setters[name] + try: + cb = self.storage[(name, real_cb)] + except KeyError: + cb = getattr(self, 'get_cb_for_%s' % name)(real_cb) + self.storage[(name, real_cb)] = cb + setter(self.itself, cb) + + def get_cb_for_StartElementHandler(self, real_cb): + def StartElement(unused, name, attrs): + # unpack name and attrs + conv = self.conv + self._flush_character_buffer() + if self.specified_attributes: + import pdb + pdb.set_trace() + max = 0 + while attrs[max]: + max += 2 # copied + if self.ordered_attributes: + res = [attrs[i] for i in range(max)] + else: + res = {} + for i in range(0, max, 2): + res[conv(attrs[i])] = conv(attrs[i + 1]) + real_cb(conv(name), res) + CB = ctypes.CFUNCTYPE(None, c_void_p, c_char_p, POINTER(c_char_p)) + return CB(StartElement) + + def get_cb_for_ExternalEntityRefHandler(self, real_cb): + def ExternalEntity(unused, context, base, sysId, pubId): + self._flush_character_buffer() + conv = self.conv + return real_cb(conv(context), conv(base), conv(sysId), + conv(pubId)) + CB = ctypes.CFUNCTYPE(c_int, c_void_p, *([c_char_p] * 4)) + return CB(ExternalEntity) + + def get_cb_for_CharacterDataHandler(self, real_cb): + def CharacterData(unused, s, lgt): + if self.buffer is None: + self._call_character_handler(self.conv(s[:lgt])) + else: + if len(self.buffer) + lgt > self.buffer_size: + self._flush_character_buffer() + if self.character_data_handler is None: + return + if lgt > self.buffer_size: + self._call_character_handler(s[:lgt]) + self.buffer = [] + else: + self.buffer.append(s[:lgt]) + CB = ctypes.CFUNCTYPE(None, c_void_p, POINTER(c_char), c_int) + return CB(CharacterData) + + def _new_callback_for_string_len(name, sign): + def get_callback_for_(self, real_cb): + def func(unused, s, len): + self._flush_character_buffer() + arg = self.conv(s[:len]) + real_cb(arg) + func.func_name = name + CB = ctypes.CFUNCTYPE(*sign) + return CB(func) + get_callback_for_.func_name = 'get_cb_for_' + name + return get_callback_for_ + + for name in ['DefaultHandlerExpand', + 'DefaultHandler']: + sign = [None, c_void_p, POINTER(c_char), c_int] + name = 'get_cb_for_' + name + locals()[name] = _new_callback_for_string_len(name, sign) + + def _new_callback_for_starargs(name, sign): + def get_callback_for_(self, real_cb): + def func(unused, *args): + self._flush_character_buffer() + args = [self.conv(arg) for arg in args] + real_cb(*args) + func.func_name = name + CB = ctypes.CFUNCTYPE(*sign) + return CB(func) + get_callback_for_.func_name = 'get_cb_for_' + name + return get_callback_for_ + + for name, num in [ + ('EndElementHandler', 1), + ('ProcessingInstructionHandler', 2), + ('UnparsedEntityDeclHandler', 5), + ('NotationDeclHandler', 4), + ('StartNamespaceDeclHandler', 2), + ('EndNamespaceDeclHandler', 1), + ('CommentHandler', 1), + ('StartCdataSectionHandler', 0), + ('EndCdataSectionHandler', 0)]: + sign = [None, c_void_p] + [c_char_p] * num + name = 'get_cb_for_' + name + locals()[name] = _new_callback_for_starargs(name, sign) + + def conv_unicode(self, s): + if s is None: + return s + return s.decode(self.encoding) + + def __setattr__(self, name, value): + # forest of ifs... + if name in ['ordered_attributes', + 'returns_unicode', 'specified_attributes']: + if value: + if name == 'returns_unicode': + self.conv = self.conv_unicode + self.__dict__[name] = 1 + else: + if name == 'returns_unicode': + self.conv = lambda s: s + self.__dict__[name] = 0 + elif name == 'buffer_text': + if value: + self.buffer = [] + else: + self._flush_character_buffer() + self.buffer = None + elif name == 'namespace_prefixes': + xxx + elif name in setters: + if name == 'CharacterDataHandler': + # XXX we need to flush buffer here + self._flush_character_buffer() + self.character_data_handler = value + #print name + #print value + #print + self._sethandler(name, value) + else: + self.__dict__[name] = value + + def __getattr__(self, name): + if name == 'buffer_text': + return self.buffer is not None + return self.__dict__[name] + + def ParseFile(self, file): + return self.Parse(file.read(), False) + +def ErrorString(errno): + xxx + +def ParserCreate(encoding=None, namespace_separator=None): + if (not isinstance(namespace_separator, str) and + not namespace_separator is None): + raise TypeError("ParserCreate() argument 2 must be string or None, not %s" % namespace_separator.__class__.__name__) + if namespace_separator is not None: + if len(namespace_separator) > 1: + raise ValueError('namespace_separator must be at most one character, omitted, or None') + if len(namespace_separator) == 0: + namespace_separator = None + return XMLParserType(encoding, namespace_separator) From santagada at codespeak.net Tue May 27 06:27:57 2008 From: santagada at codespeak.net (santagada at codespeak.net) Date: Tue, 27 May 2008 06:27:57 +0200 (CEST) Subject: [pypy-svn] r55287 - pypy/branch/js-refactoring/pypy/lang/js Message-ID: <20080527042757.45D3A4981E6@codespeak.net> Author: santagada Date: Tue May 27 06:27:53 2008 New Revision: 55287 Modified: pypy/branch/js-refactoring/pypy/lang/js/astbuilder.py pypy/branch/js-refactoring/pypy/lang/js/interpreter.py pypy/branch/js-refactoring/pypy/lang/js/jsparser.py pypy/branch/js-refactoring/pypy/lang/js/operations.py Log: astbuilder fix for callexpressions (maybe some others need this, look at jsgrammar.txt), a new array join, and set the recursion limit a little higher (cfbolz parsing needs this). from 85 to 3k tests passing on Array directory alone Modified: pypy/branch/js-refactoring/pypy/lang/js/astbuilder.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/astbuilder.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/astbuilder.py Tue May 27 06:27:53 2008 @@ -311,9 +311,16 @@ def visit_callexpression(self, node): pos = self.get_pos(node) left = self.dispatch(node.children[0]) - for rightnode in node.children[1:]: - right = self.dispatch(rightnode) - left = operations.Call(pos, left, right) + nodelist = node.children[1:] + while nodelist: + currnode = nodelist.pop(0) + if isinstance(currnode, Symbol): + op = currnode + right = self.dispatch(nodelist.pop(0)) + left = self.BINOP_TO_CLS[op.additional_info](pos, left, right) + else: + right = self.dispatch(currnode) + left = operations.Call(pos, left, right) return left Modified: pypy/branch/js-refactoring/pypy/lang/js/interpreter.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/interpreter.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/interpreter.py Tue May 27 06:27:53 2008 @@ -5,7 +5,7 @@ from pypy.lang.js.jsobj import global_context, W_Object,\ w_Undefined, W_NewBuiltin, W_IntNumber, w_Null, create_object, W_Boolean,\ W_FloatNumber, W_String, W_Builtin, W_Array, w_Null,\ - isnull_or_undefined, W_PrimitiveObject, W_ListObject + isnull_or_undefined, W_PrimitiveObject, W_ListObject, W_BaseNumber from pypy.lang.js.execution import ThrowException, JsTypeError from pypy.rlib.objectmodel import we_are_translated from pypy.rlib.streamio import open_file_as_stream @@ -96,8 +96,11 @@ def Call(self, ctx, args=[], this=None): proto = ctx.get_global().Get(ctx, 'Array').Get(ctx, 'prototype') array = W_Array(ctx, Prototype=proto, Class = proto.Class) - for i in range(len(args)): - array.Put(ctx, str(i), args[i]) + if len(args) == 1 and isinstance(args[0], W_BaseNumber): + array.Put(ctx, 'length', args[0]) + else: + for i in range(len(args)): + array.Put(ctx, str(i), args[i]) return array def Construct(self, ctx, args=[]): @@ -371,12 +374,34 @@ end = max(tmp1, tmp2) return W_String(string[start:end]) +def common_join(ctx, this, sep=','): + length = this.Get(ctx, 'length').ToUInt32(ctx) + l = [] + i = 0 + while i < length: + item = this.Get(ctx, str(i)) + if isnull_or_undefined(item): + item_string = '' + else: + item_string = item.ToString(ctx) + l.append(item_string) + i += 1 + + return sep.join(l) + class W_ArrayToString(W_NewBuiltin): def Call(self, ctx, args=[], this=None): - length = this.Get(ctx, 'length').ToUInt32(ctx) - sep = ',' - return W_String(sep.join([this.Get(ctx, str(index)).ToString(ctx) - for index in range(length)])) + return W_String(common_join(ctx, this, sep=',')) + +class W_ArrayJoin(W_NewBuiltin): + def Call(self, ctx, args=[], this=None): + if len(args) >= 1 and not args[0] is w_Undefined: + sep = args[0].ToString(ctx) + else: + sep = ',' + + return W_String(common_join(ctx, this, sep)) + class W_DateFake(W_NewBuiltin): # XXX This is temporary def Call(self, ctx, args=[], this=None): Modified: pypy/branch/js-refactoring/pypy/lang/js/jsparser.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/jsparser.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/jsparser.py Tue May 27 06:27:53 2008 @@ -1,6 +1,9 @@ from pypy.rlib.parsing.ebnfparse import parse_ebnf, make_parse_function from pypy.rlib.parsing.parsing import ParseError, Rule import py +import sys + +sys.setrecursionlimit(10000) GFILE = py.magic.autopath().dirpath().join("jsgrammar.txt") Modified: pypy/branch/js-refactoring/pypy/lang/js/operations.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/operations.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/operations.py Tue May 27 06:27:53 2008 @@ -32,18 +32,18 @@ """ Initializes the content from the AST specific for each node type """ - raise NotImplementedError + raise NotImplementedError() def emit(self, bytecode): """ Emits bytecode """ - raise NotImplementedError + raise NotImplementedError() def get_literal(self): - raise NotImplementedError + raise NotImplementedError() def get_args(self, ctx): - raise NotImplementedError + raise NotImplementedError() def __str__(self): return "%s()"%(self.__class__) From afa at codespeak.net Tue May 27 09:39:58 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 27 May 2008 09:39:58 +0200 (CEST) Subject: [pypy-svn] r55288 - pypy/dist/pypy/config Message-ID: <20080527073958.99471169EE3@codespeak.net> Author: afa Date: Tue May 27 09:39:56 2008 New Revision: 55288 Modified: pypy/dist/pypy/config/pypyoption.py Log: The signal module translates on windows. Let's pretend that it actually works. Modified: pypy/dist/pypy/config/pypyoption.py ============================================================================== --- pypy/dist/pypy/config/pypyoption.py (original) +++ pypy/dist/pypy/config/pypyoption.py Tue May 27 09:39:56 2008 @@ -35,8 +35,6 @@ del working_modules["fcntl"] del working_modules["termios"] del working_modules["_minimal_curses"] - # modules currently missing explicit windows support - del working_modules["signal"] module_dependencies = {} From antocuni at codespeak.net Tue May 27 10:19:14 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 27 May 2008 10:19:14 +0200 (CEST) Subject: [pypy-svn] r55289 - pypy/django/tests Message-ID: <20080527081914.3BAB7498194@codespeak.net> Author: antocuni Date: Tue May 27 10:19:12 2008 New Revision: 55289 Modified: pypy/django/tests/conftest.py Log: use a better name than "foo" for doctests Modified: pypy/django/tests/conftest.py ============================================================================== --- pypy/django/tests/conftest.py (original) +++ pypy/django/tests/conftest.py Tue May 27 10:19:12 2008 @@ -52,7 +52,8 @@ parser = _doctest.DocTestParser() globs = mod.__dict__.copy() assert docstring is not None - test = parser.get_doctest(docstring, globs, "foo", mod.__file__, 0) + name = os.path.basename(mod.__file__) + test = parser.get_doctest(docstring, globs, name, mod.__file__, 0) runner.run(test) if runner.failures: py.test.fail("doctest %s: %s failed out of %s" %( From antocuni at codespeak.net Tue May 27 10:23:56 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 27 May 2008 10:23:56 +0200 (CEST) Subject: [pypy-svn] r55290 - pypy/django/tests Message-ID: <20080527082356.CCB9F4981E8@codespeak.net> Author: antocuni Date: Tue May 27 10:23:53 2008 New Revision: 55290 Modified: pypy/django/tests/failures.txt Log: make this file a bit more tidy Modified: pypy/django/tests/failures.txt ============================================================================== --- pypy/django/tests/failures.txt (original) +++ pypy/django/tests/failures.txt Tue May 27 10:23:53 2008 @@ -1,50 +1,43 @@ -Tests failing because of missing expat (xml parser) ---------------------------------------------------- +Tests failing because of missing pyexpat (xml parser) +----------------------------------------------------- - modeltests/fixtures - modeltests/serializers + - modeltests/test_client + - regressiontests/fixtures_regress -(maybe there are other issues, but they are masked by xml errors) + - regressiontests/serializers_regress/tests/SerializerTests/ + test_xml_serializer + test_xml_serializer_fields + - regressiontests.forms.tests.__test__.form_tests - pyexpat -Other tests ------------ - -"some tests" fixed in r54740 (XXX: which are -"some tests") + - regressiontests.templates.tests.Templates - pyexpat -regressiontests/datastructures fixed in r55068 - -regressiontests/forms/widget_tests and others fixed in r55075 +(maybe there are other issues, but they are masked by xml errors) As of 26 May 2008 ================= -modeltests/test_client - - one test requires pyexpat - -regressiontests/serializers_regress/tests/SerializerTests/ - test_xml_serializer - test_xml_serializer_fields - - requires pyexpat - -fixtures - requires pyexpat -modeltests/serializers - requires pyexpat (can hide further errors, hard to tell) - regressiontests.i18n.tests.__test__.regressions - module print -regressiontests.forms.tests.__test__.form_tests - pyexpat - regressiontests.dispatch.tests.test_dispatcher.DispatcherTests - garbage collection not happening immediately doctest regressiontests.datastructures.tests[45] - dict subclasses regressiontests.httpwrappers.tests - dict subclasses -regressiontests.templates.tests.Templates - pyexpat + +Other tests +----------- + +"some tests" fixed in r54740 (XXX: which are +"some tests") + +regressiontests/datastructures fixed in r55068 + +regressiontests/forms/widget_tests and others fixed in r55075 From antocuni at codespeak.net Tue May 27 11:00:38 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 27 May 2008 11:00:38 +0200 (CEST) Subject: [pypy-svn] r55291 - pypy/dist/pypy/objspace/std Message-ID: <20080527090038.B8873498194@codespeak.net> Author: antocuni Date: Tue May 27 11:00:35 2008 New Revision: 55291 Modified: pypy/dist/pypy/objspace/std/dictmultiobject.py Log: remove code duplication Modified: pypy/dist/pypy/objspace/std/dictmultiobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/dictmultiobject.py (original) +++ pypy/dist/pypy/objspace/std/dictmultiobject.py Tue May 27 11:00:35 2008 @@ -1256,32 +1256,8 @@ w_dict.implementation.delitem(w_key) return w_item -app = gateway.applevel(''' - def dictrepr(currently_in_repr, d): - # Now we only handle one implementation of dicts, this one. - # The fix is to move this to dicttype.py, and do a - # multimethod lookup mapping str to StdObjSpace.str - # This cannot happen until multimethods are fixed. See dicttype.py - dict_id = id(d) - if dict_id in currently_in_repr: - return '{...}' - currently_in_repr[dict_id] = 1 - try: - items = [] - # XXX for now, we cannot use iteritems() at app-level because - # we want a reasonable result instead of a RuntimeError - # even if the dict is mutated by the repr() in the loop. - for k, v in dict.items(d): - items.append(repr(k) + ": " + repr(v)) - return "{" + ', '.join(items) + "}" - finally: - try: - del currently_in_repr[dict_id] - except: - pass -''', filename=__file__) -dictrepr = app.interphook("dictrepr") +from pypy.objspace.std.dictobject import dictrepr def repr__DictMulti(space, w_dict): if w_dict.implementation.length() == 0: From arigo at codespeak.net Tue May 27 13:42:33 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 27 May 2008 13:42:33 +0200 (CEST) Subject: [pypy-svn] r55295 - pypy/dist/pypy/module/thread/test Message-ID: <20080527114233.11A14169EB5@codespeak.net> Author: arigo Date: Tue May 27 13:42:31 2008 New Revision: 55295 Modified: pypy/dist/pypy/module/thread/test/test_ll_thread.py Log: Added some tests until I found one that explodes because of bogus interactions between threads and the framework gc. Skipped for now. Modified: pypy/dist/pypy/module/thread/test/test_ll_thread.py ============================================================================== --- pypy/dist/pypy/module/thread/test/test_ll_thread.py (original) +++ pypy/dist/pypy/module/thread/test/test_ll_thread.py Tue May 27 13:42:31 2008 @@ -1,6 +1,6 @@ from pypy.module.thread.ll_thread import * -from pypy.translator.c.test.test_genc import compile +from pypy.translator.c.test.test_boehm import AbstractGCTestClass from pypy.rpython.lltypesystem import lltype from pypy.rpython.lltypesystem.lloperation import llop from pypy.rlib.objectmodel import free_non_gc_object @@ -34,59 +34,135 @@ could_acquire_again = l.acquire(False) assert could_acquire_again -def test_start_new_thread(): - import time - - class State: - pass - state = State() - - class Z: - def __init__(self, value): - self.value = value - def __del__(self): - state.freed_counter += 1 - - class Y: - _alloc_flavor_ = 'raw' - - def bootstrap(self): - state.my_thread_ident = get_ident() - assert state.my_thread_ident == get_ident() - state.seen_value = self.z.value - self.z = None - free_non_gc_object(self) - state.done = 1 - - def g(i): - y = Y() - y.z = Z(i) - start_new_thread(Y.bootstrap, (y,)) - g._dont_inline_ = True - - def f(): - main_ident = get_ident() - assert main_ident == get_ident() - state.freed_counter = 0 - for i in range(50): - state.done = 0 - state.seen_value = 0 - g(i) +class TestUsingBoehm(AbstractGCTestClass): + gcpolicy = 'boehm' + + def test_start_new_thread(self): + import time + + class State: + pass + state = State() + + class Z: + def __init__(self, value): + self.value = value + def __del__(self): + state.freed_counter += 1 + + class Y: + _alloc_flavor_ = 'raw' + + def bootstrap(self): + state.my_thread_ident = get_ident() + assert state.my_thread_ident == get_ident() + state.seen_value = self.z.value + self.z = None + free_non_gc_object(self) + state.done = 1 + + def g(i): + y = Y() + y.z = Z(i) + start_new_thread(Y.bootstrap, (y,)) + g._dont_inline_ = True + + def f(): + main_ident = get_ident() + assert main_ident == get_ident() + state.freed_counter = 0 + for i in range(50): + state.done = 0 + state.seen_value = 0 + g(i) + willing_to_wait_more = 1000 + while not state.done: + willing_to_wait_more -= 1 + if not willing_to_wait_more: + raise Exception("thread didn't start?") + time.sleep(0.01) + assert state.my_thread_ident != main_ident + assert state.seen_value == i + # try to force Boehm to do some freeing + for i in range(3): + llop.gc__collect(lltype.Void) + return state.freed_counter + + fn = self.getcompiled(f, []) + freed_counter = fn() + print freed_counter + if self.gcpolicy == 'boehm': + assert freed_counter > 0 + else: + assert freed_counter == 50 + + def test_gc_locking(self): + import time + + class State: + pass + state = State() + + class Z: + def __init__(self, i, j): + self.i = i + self.j = j + def run(self): + j = self.j + state.gil.acquire(True) + assert j == self.j + if self.i > 1: + g(self.i-1, self.j * 2) + g(self.i-2, self.j * 2 + 1) + else: + state.answers.append(self.i) + assert j == self.j + state.gil.release() + assert j == self.j + run._dont_inline_ = True + + class Y(object): + _alloc_flavor_ = 'raw' + def bootstrap(self): + self.z.run() + self.z = None + free_non_gc_object(self) + state.done = 1 + + def g(i, j): + y = Y() + y.z = Z(i, j) + start_new_thread(Y.bootstrap, (y,)) + g._dont_inline_ = True + + def f(): + state.gil = allocate_lock_NOAUTO() + state.answers = [] + state.finished = 0 + g(7, 1) + done = False willing_to_wait_more = 1000 - while not state.done: - willing_to_wait_more -= 1 + while not done: if not willing_to_wait_more: - raise Exception("thread didn't start?") + raise Exception("didn't get enough answers: got %d," + " expected %d" % (len(state.answers), + expected)) + willing_to_wait_more -= 1 + state.gil.acquire(True) + done = len(state.answers) == expected + state.gil.release() time.sleep(0.01) - assert state.my_thread_ident != main_ident - assert state.seen_value == i - # try to force Boehm to do some freeing - for i in range(3): - llop.gc__collect(lltype.Void) - return state.freed_counter - - fn = compile(f, [], gcpolicy='boehm') - freed_counter = fn() - print freed_counter - assert freed_counter > 0 + time.sleep(0.1) + return len(state.answers) + + expected = 21 + fn = self.getcompiled(f, []) + answers = fn() + assert answers == expected + +class TestUsingFramework(TestUsingBoehm): + gcpolicy = 'generation' + + def test_gc_locking(self): + py.test.skip("in-progress") From arigo at codespeak.net Tue May 27 14:01:23 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 27 May 2008 14:01:23 +0200 (CEST) Subject: [pypy-svn] r55299 - pypy/branch/gc+thread Message-ID: <20080527120123.ABBAF4981C6@codespeak.net> Author: arigo Date: Tue May 27 14:01:21 2008 New Revision: 55299 Added: pypy/branch/gc+thread/ - copied from r55298, pypy/dist/ Log: As expected, gc+threads are becoming somewhat of a mess, so let's move this effort to a branch. From arigo at codespeak.net Tue May 27 15:37:20 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 27 May 2008 15:37:20 +0200 (CEST) Subject: [pypy-svn] r55300 - in pypy/branch/gc+thread/pypy: module/thread module/thread/test translator/c/src Message-ID: <20080527133720.452CE169E76@codespeak.net> Author: arigo Date: Tue May 27 15:37:17 2008 New Revision: 55300 Modified: pypy/branch/gc+thread/pypy/module/thread/gil.py pypy/branch/gc+thread/pypy/module/thread/ll_thread.py pypy/branch/gc+thread/pypy/module/thread/os_thread.py pypy/branch/gc+thread/pypy/module/thread/test/test_ll_thread.py pypy/branch/gc+thread/pypy/translator/c/src/thread_nt.h pypy/branch/gc+thread/pypy/translator/c/src/thread_pthread.h Log: A refactoring that is a bit of a simplification: this removes the strange raw-malloced object and replaces it with a global gc object. It also uses a regular rffi callback in start_new_thread, which allows it to reuse rffi's existing gil handling logic. Modified: pypy/branch/gc+thread/pypy/module/thread/gil.py ============================================================================== --- pypy/branch/gc+thread/pypy/module/thread/gil.py (original) +++ pypy/branch/gc+thread/pypy/module/thread/gil.py Tue May 27 15:37:17 2008 @@ -5,7 +5,7 @@ # This module adds a global lock to an object space. # If multiple threads try to execute simultaneously in this space, # all but one will be blocked. The other threads get a chance to run -# from time to time, using the executioncontext's XXX +# from time to time, using the hook yield_thread(). from pypy.module.thread import ll_thread as thread from pypy.module.thread.error import wrap_thread_error @@ -25,6 +25,7 @@ self.GIL = thread.allocate_lock_NOAUTO() except thread.error: raise wrap_thread_error(space, "can't allocate GIL") + self.GIL.acquire(True) self.enter_thread(space) # setup the main thread # add the GIL-releasing callback as an action on the space space.pending_actions.append(GILReleaseAction(self)) @@ -44,16 +45,6 @@ invoke_around_extcall(before_external_call, after_external_call) return result - def enter_thread(self, space): - "Notification that the current thread is just starting: grab the GIL." - self.GIL.acquire(True) - OSThreadLocals.enter_thread(self, space) - - def leave_thread(self, space): - "Notification that the current thread is stopping: release the GIL." - OSThreadLocals.leave_thread(self, space) - self.GIL.release() - def yield_thread(self): """Notification that the current thread is between two bytecodes: release the GIL for a little while.""" Modified: pypy/branch/gc+thread/pypy/module/thread/ll_thread.py ============================================================================== --- pypy/branch/gc+thread/pypy/module/thread/ll_thread.py (original) +++ pypy/branch/gc+thread/pypy/module/thread/ll_thread.py Tue May 27 15:37:17 2008 @@ -6,7 +6,7 @@ from pypy.rpython.annlowlevel import cast_instance_to_base_ptr from pypy.translator.tool.cbuild import ExternalCompilationInfo from pypy.rpython.lltypesystem import llmemory -import thread, py, os +import py, os from pypy.rpython.extregistry import ExtRegistryEntry from pypy.annotation import model as annmodel from pypy.rpython.lltypesystem.lltype import typeOf @@ -15,7 +15,8 @@ from distutils import sysconfig python_inc = sysconfig.get_python_inc() -error = thread.error +class error(Exception): + pass eci = ExternalCompilationInfo( includes = ['src/thread.h'], @@ -31,8 +32,17 @@ return rffi.llexternal(name, args, result, compilation_info=eci, **kwds) -CALLBACK = lltype.Ptr(lltype.FuncType([rffi.VOIDP], rffi.VOIDP)) -c_thread_start = llexternal('RPyThreadStart', [CALLBACK, rffi.VOIDP], rffi.INT) +def _emulated_start_new_thread(func): + import thread + try: + ident = thread.start_new_thread(func, ()) + except thread.error: + ident = -1 + return rffi.cast(rffi.INT, ident) + +CALLBACK = lltype.Ptr(lltype.FuncType([], lltype.Void)) +c_thread_start = llexternal('RPyThreadStart', [CALLBACK], rffi.INT, + _callable=_emulated_start_new_thread) c_thread_get_ident = llexternal('RPyThreadGetIdent', [], rffi.INT) TLOCKP = rffi.COpaquePtr('struct RPyOpaque_ThreadLock', @@ -71,55 +81,24 @@ raise error("out of resources") return Lock_NOAUTO(ll_lock) -def _start_new_thread(x, y): - return thread.start_new_thread(x, (y,)) - -def ll_start_new_thread(l_func, arg): - l_arg = cast_instance_to_base_ptr(arg) - l_arg = rffi.cast(rffi.VOIDP, l_arg) - ident = c_thread_start(l_func, l_arg) +def ll_start_new_thread(func): + ident = c_thread_start(func) if ident == -1: raise error("can't start new thread") return ident -class LLStartNewThread(ExtRegistryEntry): - _about_ = _start_new_thread - - def compute_result_annotation(self, s_func, s_arg): - bookkeeper = self.bookkeeper - s_result = bookkeeper.emulate_pbc_call(bookkeeper.position_key, - s_func, [s_arg]) - assert annmodel.s_None.contains(s_result) - return annmodel.SomeInteger() - - def specialize_call(self, hop): - rtyper = hop.rtyper - bk = rtyper.annotator.bookkeeper - r_result = rtyper.getrepr(hop.s_result) - hop.exception_is_here() - args_r = [rtyper.getrepr(s_arg) for s_arg in hop.args_s] - _callable = hop.args_s[0].const - funcptr = lltype.functionptr(CALLBACK.TO, _callable.func_name, - _callable=_callable) - func_s = bk.immutablevalue(funcptr) - s_args = [func_s, hop.args_s[1]] - obj = rtyper.getannmixlevel().delayedfunction( - ll_start_new_thread, s_args, annmodel.SomeInteger()) - bootstrap = rtyper.getannmixlevel().delayedfunction( - _callable, [hop.args_s[1]], annmodel.s_None) - vlist = [hop.inputconst(typeOf(obj), obj), - hop.inputconst(typeOf(bootstrap), bootstrap), - #hop.inputarg(args_r[0], 0), - hop.inputarg(args_r[1], 1)] - return hop.genop('direct_call', vlist, r_result) - # wrappers... def get_ident(): return c_thread_get_ident() def start_new_thread(x, y): - return _start_new_thread(x, y[0]) + """In RPython, no argument can be passed. You have to use global + variables to pass information to the new thread. That's not very + nice, but at least it avoids some levels of GC issues. + """ + assert len(y) == 0 + return ll_start_new_thread(x) class Lock(object): """ Container for low-level implementation Modified: pypy/branch/gc+thread/pypy/module/thread/os_thread.py ============================================================================== --- pypy/branch/gc+thread/pypy/module/thread/os_thread.py (original) +++ pypy/branch/gc+thread/pypy/module/thread/os_thread.py Tue May 27 15:37:17 2008 @@ -9,38 +9,65 @@ from pypy.interpreter.gateway import ObjSpace, W_Root, Arguments from pypy.rlib.objectmodel import free_non_gc_object -# This code has subtle memory management issues in order to start -# a new thread. It should work correctly with Boehm, but the framework -# GC will not see the references stored in the raw-malloced Bootstrapper -# instances => crash. It crashes with refcounting too -# (see the skipped test_raw_instance_flavor in -# rpython/memory/gctransformer/test/test_refcounting). + class Bootstrapper(object): - _alloc_flavor_ = 'raw' - - def bootstrap(self): - space = self.space + "A global container used to pass information to newly starting threads." + + # Passing a closure argument to ll_thread.start_new_thread() would be + # theoretically nicer, but comes with messy memory management issues. + # This is much more straightforward. + + # The following lock is held whenever the fields + # 'bootstrapper.w_callable' and 'bootstrapper.args' are in use. + lock = None + + def setup(space): + if bootstrapper.lock is None: + try: + bootstrapper.lock = thread.allocate_lock() + except thread.error: + raise wrap_thread_error(space, "can't allocate bootstrap lock") + setup = staticmethod(setup) + + def bootstrap(): + # Note that when this runs, we already hold the GIL. This is ensured + # by rffi's callback mecanism: we are a callback for the + # c_thread_start() external function. + space = bootstrapper.space + w_callable = bootstrapper.w_callable + args = bootstrapper.args + bootstrapper.release() + # run! space.threadlocals.enter_thread(space) try: - self.run() + bootstrapper.run(space, w_callable, args) finally: - # release ownership of these objects before we release the GIL. - # (for the refcounting gc it is necessary to reset the fields to - # None before we use free_non_gc_object(), because the latter - # doesn't know that it needs to decref the fields) - self.args = None - self.w_callable = None - # we can free the empty 'self' structure now - free_non_gc_object(self) # clean up space.threadlocals to remove the ExecutionContext - # entry corresponding to the current thread and release the GIL + # entry corresponding to the current thread space.threadlocals.leave_thread(space) + bootstrap = staticmethod(bootstrap) + + def acquire(space, w_callable, args): + # If the previous thread didn't start yet, wait until it does. + # Note that bootstrapper.lock must be a regular lock, not a NOAUTO + # lock, because the GIL must be released while we wait. + bootstrapper.lock.acquire(True) + bootstrapper.space = space + bootstrapper.w_callable = w_callable + bootstrapper.args = args + acquire = staticmethod(acquire) + + def release(): + # clean up 'bootstrapper' to make it ready for the next + # start_new_thread() and release the lock to tell that there + # isn't any bootstrapping thread left. + bootstrapper.w_callable = None + bootstrapper.args = None + bootstrapper.lock.release() + release = staticmethod(release) - def run(self): - space = self.space - w_callable = self.w_callable - args = self.args + def run(space, w_callable, args): try: space.call_args(w_callable, args) except OperationError, e: @@ -49,10 +76,14 @@ where = 'thread %d started by ' % ident e.write_unraisable(space, where, w_callable) e.clear(space) + run = staticmethod(run) + +bootstrapper = Bootstrapper() def setup_threads(space): space.threadlocals.setup_threads(space) + bootstrapper.setup(space) def start_new_thread(space, w_callable, w_args, w_kwargs=NoneNotWrapped): @@ -74,12 +105,13 @@ space.wrap("first arg must be callable")) args = Arguments.frompacked(space, w_args, w_kwargs) - boot = Bootstrapper() - boot.space = space - boot.w_callable = w_callable - boot.args = args + bootstrapper.acquire(space, w_callable, args) try: - ident = thread.start_new_thread(Bootstrapper.bootstrap, (boot,)) + try: + ident = thread.start_new_thread(bootstrapper.bootstrap, ()) + except Exception, e: + bootstrapper.release() # normally called by the new thread + raise except thread.error: raise wrap_thread_error(space, "can't start new thread") return space.wrap(ident) Modified: pypy/branch/gc+thread/pypy/module/thread/test/test_ll_thread.py ============================================================================== --- pypy/branch/gc+thread/pypy/module/thread/test/test_ll_thread.py (original) +++ pypy/branch/gc+thread/pypy/module/thread/test/test_ll_thread.py Tue May 27 15:37:17 2008 @@ -1,11 +1,16 @@ - +import gc from pypy.module.thread.ll_thread import * from pypy.translator.c.test.test_boehm import AbstractGCTestClass -from pypy.rpython.lltypesystem import lltype +from pypy.rpython.lltypesystem import lltype, rffi from pypy.rpython.lltypesystem.lloperation import llop -from pypy.rlib.objectmodel import free_non_gc_object import py +def setup_module(mod): + # Hack to avoid a deadlock if the module is run after other test files :-( + # In this module, we assume that ll_thread.start_new_thread() is not + # providing us with a GIL equivalent. + rffi.aroundstate._freeze_() + def test_lock(): l = allocate_lock() ok1 = l.acquire(True) @@ -35,8 +40,7 @@ assert could_acquire_again -class TestUsingBoehm(AbstractGCTestClass): - gcpolicy = 'boehm' +class AbstractThreadTests(AbstractGCTestClass): def test_start_new_thread(self): import time @@ -51,21 +55,16 @@ def __del__(self): state.freed_counter += 1 - class Y: - _alloc_flavor_ = 'raw' - - def bootstrap(self): - state.my_thread_ident = get_ident() - assert state.my_thread_ident == get_ident() - state.seen_value = self.z.value - self.z = None - free_non_gc_object(self) - state.done = 1 + def bootstrap(): + state.my_thread_ident = get_ident() + assert state.my_thread_ident == get_ident() + state.seen_value = state.z.value + state.z = None + state.done = 1 def g(i): - y = Y() - y.z = Z(i) - start_new_thread(Y.bootstrap, (y,)) + state.z = Z(i) + start_new_thread(bootstrap, ()) g._dont_inline_ = True def f(): @@ -76,6 +75,7 @@ state.done = 0 state.seen_value = 0 g(i) + gc.collect() willing_to_wait_more = 1000 while not state.done: willing_to_wait_more -= 1 @@ -86,7 +86,7 @@ assert state.seen_value == i # try to force Boehm to do some freeing for i in range(3): - llop.gc__collect(lltype.Void) + gc.collect() return state.freed_counter fn = self.getcompiled(f, []) @@ -110,34 +110,39 @@ self.j = j def run(self): j = self.j - state.gil.acquire(True) - assert j == self.j if self.i > 1: g(self.i-1, self.j * 2) + assert j == self.j g(self.i-2, self.j * 2 + 1) else: - state.answers.append(self.i) - assert j == self.j - state.gil.release() + if len(state.answers) % 7 == 5: + gc.collect() + state.answers.append(self.j) assert j == self.j run._dont_inline_ = True - class Y(object): - _alloc_flavor_ = 'raw' - def bootstrap(self): - self.z.run() - self.z = None - free_non_gc_object(self) - state.done = 1 + def bootstrap(): + state.gil.acquire(True) + z = state.z + state.z = None + z.run() + state.gil.release() def g(i, j): - y = Y() - y.z = Z(i, j) - start_new_thread(Y.bootstrap, (y,)) - g._dont_inline_ = True + state.z = Z(i, j) + start_new_thread(bootstrap, ()) + # now wait until the new thread really started and consumed 'z' + willing_to_wait_more = 1000 + while state.z is not None: + assert willing_to_wait_more > 0 + willing_to_wait_more -= 1 + state.gil.release() + time.sleep(0.005) + state.gil.acquire(True) def f(): state.gil = allocate_lock_NOAUTO() + state.gil.acquire(True) state.answers = [] state.finished = 0 g(7, 1) @@ -149,10 +154,11 @@ " expected %d" % (len(state.answers), expected)) willing_to_wait_more -= 1 - state.gil.acquire(True) done = len(state.answers) == expected state.gil.release() time.sleep(0.01) + state.gil.acquire(True) + state.gil.release() time.sleep(0.1) return len(state.answers) @@ -161,8 +167,14 @@ answers = fn() assert answers == expected -class TestUsingFramework(TestUsingBoehm): - gcpolicy = 'generation' +class TestRunDirectly(AbstractThreadTests): + def getcompiled(self, f, argtypes): + return f - def test_gc_locking(self): +class TestUsingBoehm(AbstractThreadTests): + gcpolicy = 'boehm' + +class TestUsingFramework(AbstractThreadTests): + gcpolicy = 'generation' + def getcompiled(self, f, argtypes): py.test.skip("in-progress") Modified: pypy/branch/gc+thread/pypy/translator/c/src/thread_nt.h ============================================================================== --- pypy/branch/gc+thread/pypy/translator/c/src/thread_nt.h (original) +++ pypy/branch/gc+thread/pypy/translator/c/src/thread_nt.h Tue May 27 15:37:17 2008 @@ -22,8 +22,7 @@ #define RPyOpaque_INITEXPR_ThreadLock { 0, 0, NULL } typedef struct { - void (*func)(void*); - void *arg; + void (*func)(void); long id; HANDLE done; } callobj; @@ -35,7 +34,7 @@ } NRMUTEX, *PNRMUTEX ; /* prototypes */ -long RPyThreadStart(void (*func)(void *), void *arg); +long RPyThreadStart(void (*func)(void)); BOOL InitializeNonRecursiveMutex(PNRMUTEX mutex); VOID DeleteNonRecursiveMutex(PNRMUTEX mutex); DWORD EnterNonRecursiveMutex(PNRMUTEX mutex, BOOL wait); @@ -63,23 +62,21 @@ { callobj *obj = (callobj*)call; /* copy callobj since other thread might free it before we're done */ - void (*func)(void*) = obj->func; - void *arg = obj->arg; + void (*func)(void) = obj->func; obj->id = RPyThreadGetIdent(); ReleaseSemaphore(obj->done, 1, NULL); - func(arg); + func(); return 0; } -long RPyThreadStart(void (*func)(void *), void *arg) +long RPyThreadStart(void (*func)(void)) { unsigned long rv; callobj obj; obj.id = -1; /* guilty until proved innocent */ obj.func = func; - obj.arg = arg; obj.done = CreateSemaphore(NULL, 0, 1, NULL); if (obj.done == NULL) return -1; Modified: pypy/branch/gc+thread/pypy/translator/c/src/thread_pthread.h ============================================================================== --- pypy/branch/gc+thread/pypy/translator/c/src/thread_pthread.h (original) +++ pypy/branch/gc+thread/pypy/translator/c/src/thread_pthread.h Tue May 27 15:37:17 2008 @@ -75,7 +75,7 @@ /* prototypes */ long RPyThreadGetIdent(void); -long RPyThreadStart(void (*func)(void *), void *arg); +long RPyThreadStart(void (*func)(void)); int RPyThreadLockInit(struct RPyOpaque_ThreadLock *lock); void RPyOpaqueDealloc_ThreadLock(struct RPyOpaque_ThreadLock *lock); int RPyThreadAcquireLock(struct RPyOpaque_ThreadLock *lock, int waitflag); @@ -105,7 +105,13 @@ #endif } -long RPyThreadStart(void (*func)(void *), void *arg) +static void *bootstrap_pthread(void *func) +{ + ((void(*)(void))func)(); + return NULL; +} + +long RPyThreadStart(void (*func)(void)) { pthread_t th; int status; @@ -129,8 +135,8 @@ #else (pthread_attr_t*)NULL, #endif - (void* (*)(void *))func, - (void *)arg + bootstrap_pthread, + (void *)func ); #if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED) From antocuni at codespeak.net Tue May 27 16:26:07 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 27 May 2008 16:26:07 +0200 (CEST) Subject: [pypy-svn] r55301 - in pypy/dist/pypy/objspace/std: . test Message-ID: <20080527142607.215E44981EB@codespeak.net> Author: antocuni Date: Tue May 27 16:26:06 2008 New Revision: 55301 Modified: pypy/dist/pypy/objspace/std/dicttype.py pypy/dist/pypy/objspace/std/test/test_dictobject.py Log: there are a lot of cases where cpython shortcuts the calls to the various dict methods, without doing a full lookup. Do the same for all the operations that are done on "self", but don't do it for the other objects, Modified: pypy/dist/pypy/objspace/std/dicttype.py ============================================================================== --- pypy/dist/pypy/objspace/std/dicttype.py (original) +++ pypy/dist/pypy/objspace/std/dicttype.py Tue May 27 16:26:06 2008 @@ -59,7 +59,8 @@ # in the following functions we use dict.__setitem__ instead of # d[k]=... because when a subclass of dict override __setitem__, - # CPython does not call it when doing builtin operations. + # CPython does not call it when doing builtin operations. The + # same for other operations. def update1(d, o): if hasattr(o, 'keys'): @@ -79,23 +80,23 @@ update1(d, kwargs) def popitem(d): - k = d.keys() + k = dict.keys(d) if not k: raise KeyError("popitem(): dictionary is empty") k = k[0] - v = d[k] - del d[k] + v = dict.__getitem__(d, k) + dict.__delitem__(d, k) return k, v def get(d, k, v=None): if k in d: - return d[k] + return dict.__getitem__(d, k) else: return v def setdefault(d, k, v=None): if k in d: - return d[k] + return dict.__getitem__(d, k) else: dict.__setitem__(d, k, v) return v @@ -105,8 +106,8 @@ raise TypeError, "pop expected at most 2 arguments, got %d" % ( 1 + len(defaults)) try: - v = d[k] - del d[k] + v = dict.__getitem__(d, k) + dict.__delitem__(d, k) except KeyError, e: if defaults: return defaults[0] @@ -115,13 +116,13 @@ return v def iteritems(d): - return iter(d.items()) + return iter(dict.items(d)) def iterkeys(d): - return iter(d.keys()) + return iter(dict.keys(d)) def itervalues(d): - return iter(d.values()) + return iter(dict.values(d)) ''', filename=__file__) #XXX what about dict.fromkeys()? Modified: pypy/dist/pypy/objspace/std/test/test_dictobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/test/test_dictobject.py (original) +++ pypy/dist/pypy/objspace/std/test/test_dictobject.py Tue May 27 16:26:06 2008 @@ -391,7 +391,7 @@ d[key] = 'bar' assert d[key] == 42 - def test_repr_with_overriden_items(self): + def test_repr_with_overridden_items(self): class D(dict): def items(self): return [] @@ -399,6 +399,25 @@ d = D([("foo", "foobar")]) assert repr(d) == "{'foo': 'foobar'}" + def test_popitem_with_overridden_delitem(self): + class D(dict): + def __delitem__(self, key): + assert False + d = D() + d['a'] = 42 + item = d.popitem() + assert item == ('a', 42) + + def test_dict_update_overridden_getitem(self): + class D(dict): + def __getitem__(self, key): + return 42 + d1 = {} + d2 = D(a='foo') + d1.update(d2) + assert d1['a'] == 42 # fails on CPython, d1['a'] == 'foo' + + # the minimal 'space' needed to use a W_DictObject class FakeSpace: def hash_w(self, obj): From antocuni at codespeak.net Tue May 27 16:27:07 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 27 May 2008 16:27:07 +0200 (CEST) Subject: [pypy-svn] r55302 - pypy/dist/pypy/doc Message-ID: <20080527142707.D4C314981EB@codespeak.net> Author: antocuni Date: Tue May 27 16:27:07 2008 New Revision: 55302 Added: pypy/dist/pypy/doc/cpython_differences.txt (contents, props changed) Log: document known differences between pypy and cpython Added: pypy/dist/pypy/doc/cpython_differences.txt ============================================================================== --- (empty file) +++ pypy/dist/pypy/doc/cpython_differences.txt Tue May 27 16:27:07 2008 @@ -0,0 +1,39 @@ +==================================== +Differences between PyPy and CPython +==================================== + +This page documents the few differences and incompatibilities between +the PyPy Python interpreter and CPython. Some of these differences +are "by design", since we think that there are cases in which the +behaviour of CPython is buggy, and we do not want to copy bugs. + +Differences that are not listed here should be considered bugs of +PyPy. + +Differences related to garbage collection strategies +---------------------------------------------------- + +XXX: write me please + + +Subclasses of builtin ``dict`` objects +-------------------------------------- + +When you pass an instance of a subclass of ``dict`` to the +``dict.update`` method, CPython simply ignores potentially overridden +methods, such as ``keys()`` or ``__getitem__()``; on the other hand, +PyPy correctly calls the overridden versions of the methods. + +For example, the following code prints ``42`` on PyPy but ``foo`` +on CPython:: + + >>>> class D(dict): + .... def __getitem__(self, key): + .... return 42 + .... + >>>> + >>>> d1 = {} + >>>> d2 = D(a='foo') + >>>> d1.update(d2) + >>>> print d1['a'] + 42 From cfbolz at codespeak.net Tue May 27 16:40:40 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 27 May 2008 16:40:40 +0200 (CEST) Subject: [pypy-svn] r55303 - pypy/dist/pypy/objspace/std Message-ID: <20080527144040.4ADEB69802E@codespeak.net> Author: cfbolz Date: Tue May 27 16:40:36 2008 New Revision: 55303 Modified: pypy/dist/pypy/objspace/std/dicttype.py Log: fix complexity of popitem, which should be faster than O(len(dict)) Modified: pypy/dist/pypy/objspace/std/dicttype.py ============================================================================== --- pypy/dist/pypy/objspace/std/dicttype.py (original) +++ pypy/dist/pypy/objspace/std/dicttype.py Tue May 27 16:40:36 2008 @@ -80,10 +80,10 @@ update1(d, kwargs) def popitem(d): - k = dict.keys(d) - if not k: + for k in dict.iterkeys(d): + break + else: raise KeyError("popitem(): dictionary is empty") - k = k[0] v = dict.__getitem__(d, k) dict.__delitem__(d, k) return k, v From arigo at codespeak.net Tue May 27 17:03:49 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 27 May 2008 17:03:49 +0200 (CEST) Subject: [pypy-svn] r55304 - in pypy/branch/gc+thread/pypy: config module/thread module/thread/test rpython rpython/lltypesystem rpython/memory rpython/memory/gctransform translator/c translator/c/test Message-ID: <20080527150349.32239168505@codespeak.net> Author: arigo Date: Tue May 27 17:03:47 2008 New Revision: 55304 Modified: pypy/branch/gc+thread/pypy/config/translationoption.py pypy/branch/gc+thread/pypy/module/thread/ll_thread.py pypy/branch/gc+thread/pypy/module/thread/test/test_ll_thread.py pypy/branch/gc+thread/pypy/rpython/llinterp.py pypy/branch/gc+thread/pypy/rpython/lltypesystem/llheap.py pypy/branch/gc+thread/pypy/rpython/lltypesystem/lloperation.py pypy/branch/gc+thread/pypy/rpython/memory/gctransform/framework.py pypy/branch/gc+thread/pypy/rpython/memory/support.py pypy/branch/gc+thread/pypy/translator/c/gc.py pypy/branch/gc+thread/pypy/translator/c/test/test_boehm.py Log: Intermediate check-in. It should kind of work, except that it doesn't. More debugging ahead. Modified: pypy/branch/gc+thread/pypy/config/translationoption.py ============================================================================== --- pypy/branch/gc+thread/pypy/config/translationoption.py (original) +++ pypy/branch/gc+thread/pypy/config/translationoption.py Tue May 27 17:03:47 2008 @@ -81,8 +81,7 @@ "asmgcc": [("translation.gc", "generation")], }), BoolOption("thread", "enable use of threading primitives", - default=False, cmdline="--thread", - requires=[("translation.gc", "boehm")]), + default=False, cmdline="--thread"), BoolOption("verbose", "Print extra information", default=False), BoolOption("debug", "Record extra annotation information", cmdline="-d --debug", default=False), Modified: pypy/branch/gc+thread/pypy/module/thread/ll_thread.py ============================================================================== --- pypy/branch/gc+thread/pypy/module/thread/ll_thread.py (original) +++ pypy/branch/gc+thread/pypy/module/thread/ll_thread.py Tue May 27 17:03:47 2008 @@ -90,7 +90,7 @@ # wrappers... def get_ident(): - return c_thread_get_ident() + return rffi.cast(lltype.Signed, c_thread_get_ident()) def start_new_thread(x, y): """In RPython, no argument can be passed. You have to use global @@ -98,7 +98,7 @@ nice, but at least it avoids some levels of GC issues. """ assert len(y) == 0 - return ll_start_new_thread(x) + return rffi.cast(lltype.Signed, ll_start_new_thread(x)) class Lock(object): """ Container for low-level implementation Modified: pypy/branch/gc+thread/pypy/module/thread/test/test_ll_thread.py ============================================================================== --- pypy/branch/gc+thread/pypy/module/thread/test/test_ll_thread.py (original) +++ pypy/branch/gc+thread/pypy/module/thread/test/test_ll_thread.py Tue May 27 17:03:47 2008 @@ -3,6 +3,7 @@ from pypy.translator.c.test.test_boehm import AbstractGCTestClass from pypy.rpython.lltypesystem import lltype, rffi from pypy.rpython.lltypesystem.lloperation import llop +from pypy.rlib.objectmodel import we_are_translated import py def setup_module(mod): @@ -41,6 +42,7 @@ class AbstractThreadTests(AbstractGCTestClass): + use_threads = True def test_start_new_thread(self): import time @@ -123,13 +125,19 @@ def bootstrap(): state.gil.acquire(True) + if we_are_translated(): + llop.gc_thread_run(lltype.Void) z = state.z state.z = None z.run() + if we_are_translated(): + llop.gc_thread_die(lltype.Void) state.gil.release() def g(i, j): state.z = Z(i, j) + if we_are_translated(): + llop.gc_thread_prepare(lltype.Void) start_new_thread(bootstrap, ()) # now wait until the new thread really started and consumed 'z' willing_to_wait_more = 1000 @@ -139,6 +147,8 @@ state.gil.release() time.sleep(0.005) state.gil.acquire(True) + if we_are_translated(): + llop.gc_thread_run(lltype.Void) def f(): state.gil = allocate_lock_NOAUTO() @@ -158,6 +168,8 @@ state.gil.release() time.sleep(0.01) state.gil.acquire(True) + if we_are_translated(): + llop.gc_thread_run(lltype.Void) state.gil.release() time.sleep(0.1) return len(state.answers) Modified: pypy/branch/gc+thread/pypy/rpython/llinterp.py ============================================================================== --- pypy/branch/gc+thread/pypy/rpython/llinterp.py (original) +++ pypy/branch/gc+thread/pypy/rpython/llinterp.py Tue May 27 17:03:47 2008 @@ -774,6 +774,12 @@ addr = llmemory.cast_ptr_to_adr(ptr) return self.heap.can_move(addr) + def op_gc_thread_run(self): + self.heap.thread_run() + + def op_gc_thread_die(self): + self.heap.thread_die() + def op_gc_free(self, addr): # what can you do? pass Modified: pypy/branch/gc+thread/pypy/rpython/lltypesystem/llheap.py ============================================================================== --- pypy/branch/gc+thread/pypy/rpython/lltypesystem/llheap.py (original) +++ pypy/branch/gc+thread/pypy/rpython/lltypesystem/llheap.py Tue May 27 17:03:47 2008 @@ -34,3 +34,9 @@ for i in range(final_size): ll_str.chars[i] = buf.chars[i] return ll_str + +def thread_run(): + pass + +def thread_die(): + pass Modified: pypy/branch/gc+thread/pypy/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/branch/gc+thread/pypy/rpython/lltypesystem/lloperation.py (original) +++ pypy/branch/gc+thread/pypy/rpython/lltypesystem/lloperation.py Tue May 27 17:03:47 2008 @@ -406,6 +406,9 @@ 'gc_id': LLOp(canraise=(MemoryError,), sideeffects=False), 'gc_set_max_heap_size': LLOp(), 'gc_can_move' : LLOp(sideeffects=False), + 'gc_thread_prepare' : LLOp(canraise=(MemoryError,)), + 'gc_thread_run' : LLOp(), + 'gc_thread_die' : LLOp(), # experimental operations in support of thread cloning, only # implemented by the Mark&Sweep GC 'gc_x_swap_pool': LLOp(canraise=(MemoryError,), canunwindgc=True), Modified: pypy/branch/gc+thread/pypy/rpython/memory/gctransform/framework.py ============================================================================== --- pypy/branch/gc+thread/pypy/rpython/memory/gctransform/framework.py (original) +++ pypy/branch/gc+thread/pypy/rpython/memory/gctransform/framework.py Tue May 27 17:03:47 2008 @@ -343,6 +343,20 @@ annmodel.s_None, minimal_transform = False) + # thread support + if translator.config.translation.thread: + if not hasattr(root_walker, "need_thread_support"): + raise Exception("%s does not support threads" % ( + root_walker.__class__.__name__,)) + root_walker.need_thread_support() + self.thread_prepare_ptr = getfn(root_walker.thread_prepare, + [], annmodel.s_None) + self.thread_run_ptr = getfn(root_walker.thread_run, + [], annmodel.s_None, + inline=True) + self.thread_die_ptr = getfn(root_walker.thread_die, + [], annmodel.s_None) + annhelper.finish() # at this point, annotate all mix-level helpers annhelper.backend_optimize() @@ -645,6 +659,18 @@ self.c_const_gc, v_size]) + def gct_gc_thread_prepare(self, hop): + assert self.translator.config.translation.thread + hop.genop("direct_call", [self.thread_prepare_ptr]) + + def gct_gc_thread_run(self, hop): + assert self.translator.config.translation.thread + hop.genop("direct_call", [self.thread_run_ptr]) + + def gct_gc_thread_die(self, hop): + assert self.translator.config.translation.thread + hop.genop("direct_call", [self.thread_die_ptr]) + def gct_malloc_nonmovable_varsize(self, hop): TYPE = hop.spaceop.result.concretetype if self.gcdata.gc.can_malloc_nonmovable(): @@ -836,6 +862,7 @@ class ShadowStackRootWalker(BaseRootWalker): need_root_stack = True + thread_setup = None def __init__(self, gctransformer): BaseRootWalker.__init__(self, gctransformer) @@ -855,12 +882,27 @@ return top self.decr_stack = decr_stack + def push_stack(self, addr): + top = self.incr_stack(1) + top.address[0] = addr + + def pop_stack(self): + top = self.decr_stack(1) + return top.address[0] + + def allocate_stack(self): + result = llmemory.raw_malloc(self.rootstacksize) + if result: + llmemory.raw_memclear(result, self.rootstacksize) + return result + def setup_root_walker(self): - stackbase = llmemory.raw_malloc(self.rootstacksize) + stackbase = self.allocate_stack() ll_assert(bool(stackbase), "could not allocate root stack") - llmemory.raw_memclear(stackbase, self.rootstacksize) self.gcdata.root_stack_top = stackbase self.gcdata.root_stack_base = stackbase + if self.thread_setup is not None: + self.thread_setup() def walk_stack_roots(self, collect_stack_root): gcdata = self.gcdata @@ -871,3 +913,103 @@ if addr.address[0] != llmemory.NULL: collect_stack_root(gc, addr) addr += sizeofaddr + + def need_thread_support(self): + from pypy.module.thread import ll_thread # xxx fish + from pypy.rpython.memory.support import AddressDict + from pypy.rpython.memory.support import copy_without_null_values + gcdata = self.gcdata + # the interfacing between the threads and the GC is done via + # three completely ad-hoc operations at the moment: + # gc_thread_prepare, gc_thread_run, gc_thread_die. + # See docstrings below. + + def get_aid(): + """Return the thread identifier, cast to an (opaque) address.""" + return llmemory.cast_int_to_adr(ll_thread.get_ident()) + + def thread_setup(): + """Called once when the program starts.""" + aid = get_aid() + gcdata.main_thread = aid + gcdata.active_thread = aid + gcdata.thread_stacks = AddressDict() # {aid: root_stack_top} + gcdata._fresh_rootstack = llmemory.NULL + gcdata.dead_threads_count = 0 + + def thread_prepare(): + """Called just before thread.start_new_thread(). This + allocates a new shadow stack to be used by the future + thread. If memory runs out, this raises a MemoryError + (which can be handled by the caller instead of just getting + ignored if it was raised in the newly starting thread). + """ + if not gcdata._fresh_rootstack: + gcdata._fresh_rootstack = self.allocate_stack() + if not gcdata._fresh_rootstack: + raise MemoryError + + def thread_run(): + """Called whenever the current thread (re-)acquired the GIL. + This should ensure that the shadow stack installed in + gcdata.root_stack_top/root_stack_base is the one corresponding + to the current thread. + """ + aid = get_aid() + if gcdata.active_thread != aid: + switch_shadow_stacks(aid) + + def thread_die(): + """Called just before the final GIL release done by a dying + thread. After a thread_die(), no more gc operation should + occur in this thread. + """ + aid = get_aid() + gcdata.thread_stacks.setitem(aid, llmemory.NULL) + old = gcdata.root_stack_base + if gcdata._fresh_rootstack == llmemory.NULL: + gcdata._fresh_rootstack = old + else: + llmemory.raw_free(old) + install_new_stack(gcdata.main_thread) + # from time to time, rehash the dictionary to remove + # old NULL entries + gcdata.dead_threads_count += 1 + if (gcdata.dead_threads_count & 511) == 0: + gcdata.thread_stacks = copy_without_null_values( + gcdata.thread_stacks) + + def switch_shadow_stacks(new_aid): + save_away_current_stack() + install_new_stack(new_aid) + switch_shadow_stacks._dont_inline_ = True + + def save_away_current_stack(): + old_aid = gcdata.active_thread + # save root_stack_base on the top of the stack + self.push_stack(gcdata.root_stack_base) + # store root_stack_top into the dictionary + gcdata.thread_stacks.setitem(old_aid, gcdata.root_stack_top) + + def install_new_stack(new_aid): + # look for the new stack top + top = gcdata.thread_stacks.get(new_aid, llmemory.NULL) + if top == llmemory.NULL: + # first time we see this thread. It is an error if no + # fresh new stack is waiting. + base = gcdata._fresh_rootstack + gcdata._fresh_rootstack = llmemory.NULL + ll_assert(base != llmemory.NULL, "missing gc_thread_prepare") + gcdata.root_stack_top = base + gcdata.root_stack_base = base + else: + # restore the root_stack_base from the top of the stack + gcdata.root_stack_top = top + gcdata.root_stack_base = self.pop_stack() + # done + gcdata.active_thread = new_aid + + self.thread_setup = thread_setup + self.thread_prepare = thread_prepare + self.thread_run = thread_run + self.thread_die = thread_die Modified: pypy/branch/gc+thread/pypy/rpython/memory/support.py ============================================================================== --- pypy/branch/gc+thread/pypy/rpython/memory/support.py (original) +++ pypy/branch/gc+thread/pypy/rpython/memory/support.py Tue May 27 17:03:47 2008 @@ -305,3 +305,19 @@ arg.setitem(newkey, value) return callback _get_updater._annspecialcase_ = 'specialize:memo' + + +def copy_without_null_values(dict): + """Make a copy of 'dict' without the key/value pairs where value==NULL.""" + newdict = AddressDict + if not we_are_translated(): + # when not translated, return a dict of the same kind as 'dict' + if not isinstance(dict, BasicAddressDict): + from pypy.rpython.memory.lldict import newdict + result = newdict() + dict.foreach(_null_value_checker, result) + return result + +def _null_value_checker(key, value, arg): + if value: + arg.setitem(key, value) Modified: pypy/branch/gc+thread/pypy/translator/c/gc.py ============================================================================== --- pypy/branch/gc+thread/pypy/translator/c/gc.py (original) +++ pypy/branch/gc+thread/pypy/translator/c/gc.py Tue May 27 17:03:47 2008 @@ -72,6 +72,15 @@ def OP_GC_SET_MAX_HEAP_SIZE(self, funcgen, op): return '' + def OP_GC_THREAD_PREPARE(self, funcgen, op): + return '' + + def OP_GC_THREAD_RUN(self, funcgen, op): + return '' + + def OP_GC_THREAD_DIE(self, funcgen, op): + return '' + class RefcountingInfo: static_deallocator = None Modified: pypy/branch/gc+thread/pypy/translator/c/test/test_boehm.py ============================================================================== --- pypy/branch/gc+thread/pypy/translator/c/test/test_boehm.py (original) +++ pypy/branch/gc+thread/pypy/translator/c/test/test_boehm.py Tue May 27 17:03:47 2008 @@ -13,6 +13,7 @@ class AbstractGCTestClass(object): gcpolicy = "boehm" stacklessgc = False + use_threads = False # deal with cleanups def setup_method(self, meth): @@ -27,6 +28,7 @@ from pypy.config.pypyoption import get_pypy_config config = get_pypy_config(translating=True) config.translation.gc = self.gcpolicy + config.translation.thread = self.use_threads if self.stacklessgc: config.translation.gcrootfinder = "stackless" config.translation.simplifying = True From fijal at codespeak.net Tue May 27 17:16:02 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 27 May 2008 17:16:02 +0200 (CEST) Subject: [pypy-svn] r55305 - pypy/dist/pypy/doc Message-ID: <20080527151602.5EBB82D8004@codespeak.net> Author: fijal Date: Tue May 27 17:16:02 2008 New Revision: 55305 Modified: pypy/dist/pypy/doc/cpython_differences.txt Log: Document this one Modified: pypy/dist/pypy/doc/cpython_differences.txt ============================================================================== --- pypy/dist/pypy/doc/cpython_differences.txt (original) +++ pypy/dist/pypy/doc/cpython_differences.txt Tue May 27 17:16:02 2008 @@ -37,3 +37,11 @@ >>>> d1.update(d2) >>>> print d1['a'] 42 + +Comparison differencies +----------------------- + +When custom \_\_eq\_\_ function on object (or any other rich comparison +method) raises an exception, we don't swallow the exception and instead +report it to user. + From fijal at codespeak.net Tue May 27 17:49:35 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 27 May 2008 17:49:35 +0200 (CEST) Subject: [pypy-svn] r55306 - in pypy/dist/pypy/module/_rawffi: . test Message-ID: <20080527154935.DBDE42D8004@codespeak.net> Author: fijal Date: Tue May 27 17:49:33 2008 New Revision: 55306 Modified: pypy/dist/pypy/module/_rawffi/callback.py pypy/dist/pypy/module/_rawffi/test/test__rawffi.py Log: * Print application traceback when failed (this is yet another level, it's good to be never sure...) * Fix tests Modified: pypy/dist/pypy/module/_rawffi/callback.py ============================================================================== --- pypy/dist/pypy/module/_rawffi/callback.py (original) +++ pypy/dist/pypy/module/_rawffi/callback.py Tue May 27 17:49:33 2008 @@ -10,6 +10,17 @@ wrap_value, unwrap_value, unwrap_truncate_int, letter2tp from pypy.rlib.libffi import USERDATA_P, CallbackFuncPtr from pypy.module._rawffi.tracker import tracker +from pypy.interpreter.error import OperationError +from pypy.interpreter import gateway + +app = gateway.applevel(''' + def tbprint(tb, err): + import traceback, sys + traceback.print_tb(tb) + print >>sys.stderr, err +''', filename=__file__) + +tbprint = app.interphook("tbprint") def callback(ll_args, ll_res, ll_userdata): userdata = rffi.cast(USERDATA_P, ll_userdata) @@ -18,11 +29,15 @@ res = rffi.cast(rffi.VOIDPP, ll_res) argtypes = callback_ptr.args space = callback_ptr.space - w_args = space.newlist([space.wrap(rffi.cast(rffi.UINT, ll_args[i])) - for i in range(len(argtypes))]) - w_res = space.call(w_callable, w_args) - unwrap_value(space, push_elem, ll_res, 0, - letter2tp(space, callback_ptr.result), w_res) + try: + w_args = space.newlist([space.wrap(rffi.cast(rffi.UINT, ll_args[i])) + for i in range(len(argtypes))]) + w_res = space.call(w_callable, w_args) + unwrap_value(space, push_elem, ll_res, 0, + letter2tp(space, callback_ptr.result), w_res) + except OperationError, e: + tbprint(space, space.wrap(e.application_traceback), + space.wrap(e.errorstr(space))) # XXX some weird hackery to be able to recover W_CallbackPtr object # out of number Modified: pypy/dist/pypy/module/_rawffi/test/test__rawffi.py ============================================================================== --- pypy/dist/pypy/module/_rawffi/test/test__rawffi.py (original) +++ pypy/dist/pypy/module/_rawffi/test/test__rawffi.py Tue May 27 17:49:33 2008 @@ -453,7 +453,6 @@ arg1.free() def test_callback(self): - skip("FIXME: compare actually receives a pair of int**") import _rawffi import struct libc = _rawffi.get_libc() @@ -464,8 +463,8 @@ resarray = _rawffi.Array('i')(1) bogus_args = False def compare(a, b): - a1 = _rawffi.Array('i').fromaddress(a, 1) - a2 = _rawffi.Array('i').fromaddress(b, 1) + a1 = _rawffi.Array('i').fromaddress(_rawffi.Array('i').fromaddress(a, 1)[0], 1) + a2 = _rawffi.Array('i').fromaddress(_rawffi.Array('i').fromaddress(b, 1)[0], 1) if a1[0] not in [1,2,3,4] or a2[0] not in [1,2,3,4]: print "comparing", a1[0], "with", a2[0] bogus_args = True @@ -505,6 +504,30 @@ a1.free() del cb + def test_raising_callback(self): + import _rawffi, sys + import StringIO + lib = _rawffi.CDLL(self.lib_name) + err = StringIO.StringIO() + orig = sys.stderr + sys.stderr = err + try: + runcallback = lib.ptr('runcallback', ['P'], 'q') + def callback(): + 1/0 + + cb = _rawffi.CallbackPtr(callback, [], 'q') + a1 = cb.byptr() + res = runcallback(a1) + a1.free() + del cb + val = err.getvalue() + assert 'ZeroDivisionError' in val + assert 'callback' in val + finally: + sys.stderr = orig + + def test_setattr_struct(self): import _rawffi X = _rawffi.Structure([('value1', 'i'), ('value2', 'i')]) @@ -771,16 +794,19 @@ def test_structure_autofree(self): import gc, _rawffi + gc.collect() S = _rawffi.Structure([('x', 'i')]) oldnum = _rawffi._num_of_allocated_objects() s = S(autofree=True) s.x = 3 s = None gc.collect() + gc.collect() assert oldnum == _rawffi._num_of_allocated_objects() def test_array_autofree(self): import gc, _rawffi + gc.collect() oldnum = _rawffi._num_of_allocated_objects() A = _rawffi.Array('c') @@ -790,6 +816,5 @@ gc.collect() assert oldnum == _rawffi._num_of_allocated_objects() - def teardown_class(cls): Tracker.DO_TRACING = False From fijal at codespeak.net Tue May 27 19:00:11 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 27 May 2008 19:00:11 +0200 (CEST) Subject: [pypy-svn] r55308 - pypy/dist/pypy/module/_rawffi Message-ID: <20080527170011.E91802D8004@codespeak.net> Author: fijal Date: Tue May 27 19:00:09 2008 New Revision: 55308 Modified: pypy/dist/pypy/module/_rawffi/callback.py Log: Don't unwrap void result Modified: pypy/dist/pypy/module/_rawffi/callback.py ============================================================================== --- pypy/dist/pypy/module/_rawffi/callback.py (original) +++ pypy/dist/pypy/module/_rawffi/callback.py Tue May 27 19:00:09 2008 @@ -33,8 +33,9 @@ w_args = space.newlist([space.wrap(rffi.cast(rffi.UINT, ll_args[i])) for i in range(len(argtypes))]) w_res = space.call(w_callable, w_args) - unwrap_value(space, push_elem, ll_res, 0, - letter2tp(space, callback_ptr.result), w_res) + if callback_ptr.res != 'O': # don't return void + unwrap_value(space, push_elem, ll_res, 0, + letter2tp(space, callback_ptr.result), w_res) except OperationError, e: tbprint(space, space.wrap(e.application_traceback), space.wrap(e.errorstr(space))) From fijal at codespeak.net Tue May 27 19:03:41 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 27 May 2008 19:03:41 +0200 (CEST) Subject: [pypy-svn] r55309 - pypy/dist/pypy/lib Message-ID: <20080527170341.8DD692D8006@codespeak.net> Author: fijal Date: Tue May 27 19:03:40 2008 New Revision: 55309 Modified: pypy/dist/pypy/lib/pyexpat.py Log: Few more checkers, now it passes the test suite Modified: pypy/dist/pypy/lib/pyexpat.py ============================================================================== --- pypy/dist/pypy/lib/pyexpat.py (original) +++ pypy/dist/pypy/lib/pyexpat.py Tue May 27 19:03:40 2008 @@ -32,6 +32,12 @@ XML_Parse = lib.XML_Parse XML_Parse.args = [XML_Parser, ctypes.c_char_p, ctypes.c_int, ctypes.c_int] XML_Parse.result = ctypes.c_int +currents = ['CurrentLineNumber', 'CurrentColumnNumber', + 'CurrentByteIndex'] +for name in currents: + func = getattr(lib, 'XML_Get' + name) + func.args = [XML_Parser] + func.result = c_int handler_names = [ 'StartElement', @@ -148,8 +154,11 @@ def ExternalEntity(unused, context, base, sysId, pubId): self._flush_character_buffer() conv = self.conv - return real_cb(conv(context), conv(base), conv(sysId), - conv(pubId)) + res = real_cb(conv(context), conv(base), conv(sysId), + conv(pubId)) + if res is None: + return 0 + return res CB = ctypes.CFUNCTYPE(c_int, c_void_p, *([c_char_p] * 4)) return CB(ExternalEntity) @@ -254,6 +263,8 @@ def __getattr__(self, name): if name == 'buffer_text': return self.buffer is not None + elif name in currents: + return getattr(lib, 'XML_Get' + name)(self.itself) return self.__dict__[name] def ParseFile(self, file): From antocuni at codespeak.net Tue May 27 19:19:35 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 27 May 2008 19:19:35 +0200 (CEST) Subject: [pypy-svn] r55310 - pypy/branch/oo-jit/pypy/translator/cli Message-ID: <20080527171935.330862D8009@codespeak.net> Author: antocuni Date: Tue May 27 19:19:34 2008 New Revision: 55310 Modified: pypy/branch/oo-jit/pypy/translator/cli/class_.py Log: it seems that this check is no longer needed these days, and moreover it breaks the translation when using --jit. Not sure why I added it, need more investigation. Modified: pypy/branch/oo-jit/pypy/translator/cli/class_.py ============================================================================== --- pypy/branch/oo-jit/pypy/translator/cli/class_.py (original) +++ pypy/branch/oo-jit/pypy/translator/cli/class_.py Tue May 27 19:19:34 2008 @@ -98,8 +98,8 @@ # there would be a type mismatch. args = m_meth.graph.getargs() SELF = args[0].concretetype - if not ootype.isSubclass(self.INSTANCE, SELF): - continue +## if not ootype.isSubclass(self.INSTANCE, SELF): +## continue f = self.db.genoo.Function(self.db, m_meth.graph, m_name, is_method = True) f.render(ilasm) else: From tverwaes at codespeak.net Tue May 27 19:29:55 2008 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Tue, 27 May 2008 19:29:55 +0200 (CEST) Subject: [pypy-svn] r55311 - pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk Message-ID: <20080527172955.1428C168525@codespeak.net> Author: tverwaes Date: Tue May 27 19:29:52 2008 New Revision: 55311 Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/primitives.py Log: fixing semantics of become Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/primitives.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/primitives.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/primitives.py Tue May 27 19:29:52 2008 @@ -504,9 +504,21 @@ @expose_primitive(BECOME, unwrap_spec=[object, object]) def func(interp, w_rcvr, w_new): - if w_rcvr.become(w_new): - return w_rcvr - raise PrimitiveFailedError + if w_rcvr.size() != w_new.size(): + raise PrimitiveFailedError + w_lefts = [] + w_rights = [] + for i in range(w_rcvr.size()): + w_left = w_rcvr.at0(interp.space, i) + w_right = w_new.at0(interp.space, i) + if w_left.become(w_right): + w_lefts.append(w_left) + w_rights.append(w_right) + else: + for i in range(len(w_lefts)): + w_lefts[i].become(w_rights[i]) + raise PrimitiveFailedError() + return w_rcvr def fake_bytes_left(interp): return interp.space.wrap_int(2**20) # XXX we don't know how to do this :-( From fijal at codespeak.net Tue May 27 19:34:27 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 27 May 2008 19:34:27 +0200 (CEST) Subject: [pypy-svn] r55312 - pypy/dist/pypy/lib Message-ID: <20080527173427.5965869802E@codespeak.net> Author: fijal Date: Tue May 27 19:34:25 2008 New Revision: 55312 Modified: pypy/dist/pypy/lib/pyexpat.py Log: Enough support to run the same amount of minidom tests as python2.5 Modified: pypy/dist/pypy/lib/pyexpat.py ============================================================================== --- pypy/dist/pypy/lib/pyexpat.py (original) +++ pypy/dist/pypy/lib/pyexpat.py Tue May 27 19:34:25 2008 @@ -39,6 +39,13 @@ func.args = [XML_Parser] func.result = c_int +XML_SetReturnNSTriplet = lib.XML_SetReturnNSTriplet +XML_SetReturnNSTriplet.args = [XML_Parser, c_int] +XML_SetReturnNSTriplet.result = None +XML_GetSpecifiedAttributeCount = lib.XML_GetSpecifiedAttributeCount +XML_GetSpecifiedAttributeCount.args = [XML_Parser] +XML_GetSpecifiedAttributeCount.result = c_int + handler_names = [ 'StartElement', 'EndElement', @@ -101,6 +108,7 @@ self.buffer = None self.buffer_size = 8192 self.character_data_handler = None + self.intern = {} def _flush_character_buffer(self): if not self.buffer: @@ -127,6 +135,9 @@ except KeyError: cb = getattr(self, 'get_cb_for_%s' % name)(real_cb) self.storage[(name, real_cb)] = cb + except TypeError: + # weellll... + cb = getattr(self, 'get_cb_for_%s' % name)(real_cb) setter(self.itself, cb) def get_cb_for_StartElementHandler(self, real_cb): @@ -135,9 +146,9 @@ conv = self.conv self._flush_character_buffer() if self.specified_attributes: - import pdb - pdb.set_trace() - max = 0 + max = XML_GetSpecifiedAttributeCount(self.itself) + else: + max = 0 while attrs[max]: max += 2 # copied if self.ordered_attributes: @@ -179,6 +190,26 @@ CB = ctypes.CFUNCTYPE(None, c_void_p, POINTER(c_char), c_int) return CB(CharacterData) + def get_cb_for_EntityDeclHandler(self, real_cb): + def EntityDecl(unused, ename, is_param, value, _, base, system_id, + pub_id, not_name): + + self._flush_character_buffer() + args = [ename, is_param, value, base, system_id, + pub_id, not_name] + args = [self.conv(arg) for arg in args] + real_cb(*args) + CB = ctypes.CFUNCTYPE(None, c_void_p, c_char_p, c_int, c_char_p, + c_int, c_char_p, c_char_p, c_char_p, c_char_p) + return CB(EntityDecl) + + def get_cb_for_ElementDeclHandler(self, real_cb): + # XXX this is broken, needs tests + def ElementDecl(unused, *args): + pass + CB = ctypes.CFUNCTYPE(None, c_void_p, c_char_p, c_void_p) + return CB(ElementDecl) + def _new_callback_for_string_len(name, sign): def get_callback_for_(self, real_cb): def func(unused, s, len): @@ -209,7 +240,7 @@ get_callback_for_.func_name = 'get_cb_for_' + name return get_callback_for_ - for name, num in [ + for name, num_or_sign in [ ('EndElementHandler', 1), ('ProcessingInstructionHandler', 2), ('UnparsedEntityDeclHandler', 5), @@ -218,13 +249,21 @@ ('EndNamespaceDeclHandler', 1), ('CommentHandler', 1), ('StartCdataSectionHandler', 0), - ('EndCdataSectionHandler', 0)]: - sign = [None, c_void_p] + [c_char_p] * num + ('EndCdataSectionHandler', 0), + ('StartDoctypeDeclHandler', [None, c_void_p] + [c_char_p] * 3 + [c_int]), + ('XmlDeclHandler', [None, c_void_p, c_char_p, c_char_p, c_int]), + ('AttlistDeclHandler', [None, c_void_p] + [c_char_p] * 4 + [c_int]), + ('EndDoctypeDeclHandler', 0), + ]: + if isinstance(num_or_sign, int): + sign = [None, c_void_p] + [c_char_p] * num_or_sign + else: + sign = num_or_sign name = 'get_cb_for_' + name locals()[name] = _new_callback_for_starargs(name, sign) def conv_unicode(self, s): - if s is None: + if s is None or isinstance(s, int): return s return s.decode(self.encoding) @@ -247,7 +286,7 @@ self._flush_character_buffer() self.buffer = None elif name == 'namespace_prefixes': - xxx + XML_SetReturnNSTriplet(self.itself, int(bool(value))) elif name in setters: if name == 'CharacterDataHandler': # XXX we need to flush buffer here From arigo at codespeak.net Tue May 27 19:47:40 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 27 May 2008 19:47:40 +0200 (CEST) Subject: [pypy-svn] r55313 - in pypy/branch/gc+thread/pypy: module/thread/test rpython/memory/gctransform Message-ID: <20080527174740.39DFE69802E@codespeak.net> Author: arigo Date: Tue May 27 19:47:36 2008 New Revision: 55313 Modified: pypy/branch/gc+thread/pypy/module/thread/test/test_ll_thread.py pypy/branch/gc+thread/pypy/rpython/memory/gctransform/framework.py Log: Fix the bug. Basic tests work now. Modified: pypy/branch/gc+thread/pypy/module/thread/test/test_ll_thread.py ============================================================================== --- pypy/branch/gc+thread/pypy/module/thread/test/test_ll_thread.py (original) +++ pypy/branch/gc+thread/pypy/module/thread/test/test_ll_thread.py Tue May 27 19:47:36 2008 @@ -188,5 +188,3 @@ class TestUsingFramework(AbstractThreadTests): gcpolicy = 'generation' - def getcompiled(self, f, argtypes): - py.test.skip("in-progress") Modified: pypy/branch/gc+thread/pypy/rpython/memory/gctransform/framework.py ============================================================================== --- pypy/branch/gc+thread/pypy/rpython/memory/gctransform/framework.py (original) +++ pypy/branch/gc+thread/pypy/rpython/memory/gctransform/framework.py Tue May 27 19:47:36 2008 @@ -863,6 +863,7 @@ class ShadowStackRootWalker(BaseRootWalker): need_root_stack = True thread_setup = None + collect_stacks_from_other_threads = None def __init__(self, gctransformer): BaseRootWalker.__init__(self, gctransformer) @@ -913,6 +914,8 @@ if addr.address[0] != llmemory.NULL: collect_stack_root(gc, addr) addr += sizeofaddr + if self.collect_stacks_from_other_threads is not None: + self.collect_stacks_from_other_threads(collect_stack_root) def need_thread_support(self): from pypy.module.thread import ll_thread # xxx fish @@ -1009,7 +1012,21 @@ # done gcdata.active_thread = new_aid + def collect_stack(aid, stacktop, callback): + if stacktop != llmemory.NULL: + gc = self.gc + end = stacktop - sizeofaddr + addr = end.address[0] + while addr != end: + if addr.address[0] != llmemory.NULL: + callback(gc, addr) + addr += sizeofaddr + + def collect_more_stacks(callback): + gcdata.thread_stacks.foreach(collect_stack, callback) + self.thread_setup = thread_setup self.thread_prepare = thread_prepare self.thread_run = thread_run self.thread_die = thread_die + self.collect_stacks_from_other_threads = collect_more_stacks From fijal at codespeak.net Tue May 27 19:57:53 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 27 May 2008 19:57:53 +0200 (CEST) Subject: [pypy-svn] r55314 - pypy/dist/pypy/lib Message-ID: <20080527175753.7546169802E@codespeak.net> Author: fijal Date: Tue May 27 19:57:52 2008 New Revision: 55314 Modified: pypy/dist/pypy/lib/pyexpat.py Log: Few constants and one method Modified: pypy/dist/pypy/lib/pyexpat.py ============================================================================== --- pypy/dist/pypy/lib/pyexpat.py (original) +++ pypy/dist/pypy/lib/pyexpat.py Tue May 27 19:57:52 2008 @@ -16,10 +16,14 @@ XML_Char = configure.SimpleType('XML_Char', ctypes.c_char) XML_COMBINED_VERSION = configure.ConstantInteger('XML_COMBINED_VERSION') + for name in ['XML_PARAM_ENTITY_PARSING_NEVER', + 'XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE', + 'XML_PARAM_ENTITY_PARSING_ALWAYS']: + locals()[name] = configure.ConstantInteger(name) info = configure.configure(CConfigure) -XML_Char = info['XML_Char'] -XML_COMBINED_VERSION = info['XML_COMBINED_VERSION'] +for k, v in info.items(): + globals()[k] = v XML_Parser = ctypes.c_void_p # an opaque pointer assert XML_Char is ctypes.c_char # this assumption is everywhere in # cpython's expat, let's explode @@ -45,6 +49,9 @@ XML_GetSpecifiedAttributeCount = lib.XML_GetSpecifiedAttributeCount XML_GetSpecifiedAttributeCount.args = [XML_Parser] XML_GetSpecifiedAttributeCount.result = c_int +XML_SetParamEntityParsing = lib.XML_SetParamEntityParsing +XML_SetParamEntityParsing.args = [XML_Parser, c_int] +XML_SetParamEntityParsing.result = None handler_names = [ 'StartElement', @@ -254,6 +261,7 @@ ('XmlDeclHandler', [None, c_void_p, c_char_p, c_char_p, c_int]), ('AttlistDeclHandler', [None, c_void_p] + [c_char_p] * 4 + [c_int]), ('EndDoctypeDeclHandler', 0), + ('SkippedEntityHandler', [None, c_void_p, c_char_p, c_int]), ]: if isinstance(num_or_sign, int): sign = [None, c_void_p] + [c_char_p] * num_or_sign @@ -299,6 +307,9 @@ else: self.__dict__[name] = value + def SetParamEntityParsing(self, arg): + XML_SetParamEntityParsing(self.itself, arg) + def __getattr__(self, name): if name == 'buffer_text': return self.buffer is not None @@ -312,7 +323,7 @@ def ErrorString(errno): xxx -def ParserCreate(encoding=None, namespace_separator=None): +def ParserCreate(encoding=None, namespace_separator=None, intern=None): if (not isinstance(namespace_separator, str) and not namespace_separator is None): raise TypeError("ParserCreate() argument 2 must be string or None, not %s" % namespace_separator.__class__.__name__) From arigo at codespeak.net Tue May 27 20:15:46 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 27 May 2008 20:15:46 +0200 (CEST) Subject: [pypy-svn] r55316 - in pypy/branch/gc+thread/pypy/module/thread: . test Message-ID: <20080527181546.DCDB9169DB1@codespeak.net> Author: arigo Date: Tue May 27 20:15:44 2008 New Revision: 55316 Modified: pypy/branch/gc+thread/pypy/module/thread/gil.py pypy/branch/gc+thread/pypy/module/thread/ll_thread.py pypy/branch/gc+thread/pypy/module/thread/os_thread.py pypy/branch/gc+thread/pypy/module/thread/test/test_ll_thread.py Log: Use the special gc-thread operations in the PyPy mixedmodule too. Modified: pypy/branch/gc+thread/pypy/module/thread/gil.py ============================================================================== --- pypy/branch/gc+thread/pypy/module/thread/gil.py (original) +++ pypy/branch/gc+thread/pypy/module/thread/gil.py Tue May 27 20:15:44 2008 @@ -53,6 +53,7 @@ # This is a single external function so that we are sure that nothing # occurs between the release and the acquire, e.g. no GC operation. GIL.fused_release_acquire() + thread.gc_thread_run() def getGIL(self): return self.GIL # XXX temporary hack! @@ -87,4 +88,5 @@ def after_external_call(): e = get_errno() spacestate.GIL.acquire(True) + thread.gc_thread_run() set_errno(e) Modified: pypy/branch/gc+thread/pypy/module/thread/ll_thread.py ============================================================================== --- pypy/branch/gc+thread/pypy/module/thread/ll_thread.py (original) +++ pypy/branch/gc+thread/pypy/module/thread/ll_thread.py Tue May 27 20:15:44 2008 @@ -11,6 +11,8 @@ from pypy.annotation import model as annmodel from pypy.rpython.lltypesystem.lltype import typeOf from pypy.rlib.debug import ll_assert +from pypy.rlib.objectmodel import we_are_translated +from pypy.rpython.lltypesystem.lloperation import llop from pypy.tool import autopath from distutils import sysconfig python_inc = sysconfig.get_python_inc() @@ -141,3 +143,32 @@ def __del__(self): lltype.free(self._lock, flavor='raw') + +# ____________________________________________________________ +# +# Thread integration. +# These are three completely ad-hoc operations at the moment. + +def gc_thread_prepare(): + """To call just before thread.start_new_thread(). This + allocates a new shadow stack to be used by the future + thread. If memory runs out, this raises a MemoryError + (which can be handled by the caller instead of just getting + ignored if it was raised in the newly starting thread). + """ + if we_are_translated(): + llop.gc_thread_prepare(lltype.Void) + +def gc_thread_run(): + """To call whenever the current thread (re-)acquired the GIL. + """ + if we_are_translated(): + llop.gc_thread_run(lltype.Void) + +def gc_thread_die(): + """To call just before the final GIL release done by a dying + thread. After a thread_die(), no more gc operation should + occur in this thread. + """ + if we_are_translated(): + llop.gc_thread_die(lltype.Void) Modified: pypy/branch/gc+thread/pypy/module/thread/os_thread.py ============================================================================== --- pypy/branch/gc+thread/pypy/module/thread/os_thread.py (original) +++ pypy/branch/gc+thread/pypy/module/thread/os_thread.py Tue May 27 20:15:44 2008 @@ -45,7 +45,10 @@ finally: # clean up space.threadlocals to remove the ExecutionContext # entry corresponding to the current thread - space.threadlocals.leave_thread(space) + try: + space.threadlocals.leave_thread(space) + finally: + thread.gc_thread_die() bootstrap = staticmethod(bootstrap) def acquire(space, w_callable, args): @@ -108,6 +111,7 @@ bootstrapper.acquire(space, w_callable, args) try: try: + thread.gc_thread_prepare() ident = thread.start_new_thread(bootstrapper.bootstrap, ()) except Exception, e: bootstrapper.release() # normally called by the new thread Modified: pypy/branch/gc+thread/pypy/module/thread/test/test_ll_thread.py ============================================================================== --- pypy/branch/gc+thread/pypy/module/thread/test/test_ll_thread.py (original) +++ pypy/branch/gc+thread/pypy/module/thread/test/test_ll_thread.py Tue May 27 20:15:44 2008 @@ -2,8 +2,6 @@ from pypy.module.thread.ll_thread import * from pypy.translator.c.test.test_boehm import AbstractGCTestClass from pypy.rpython.lltypesystem import lltype, rffi -from pypy.rpython.lltypesystem.lloperation import llop -from pypy.rlib.objectmodel import we_are_translated import py def setup_module(mod): @@ -125,19 +123,16 @@ def bootstrap(): state.gil.acquire(True) - if we_are_translated(): - llop.gc_thread_run(lltype.Void) + gc_thread_run() z = state.z state.z = None z.run() - if we_are_translated(): - llop.gc_thread_die(lltype.Void) + gc_thread_die() state.gil.release() def g(i, j): state.z = Z(i, j) - if we_are_translated(): - llop.gc_thread_prepare(lltype.Void) + gc_thread_prepare() start_new_thread(bootstrap, ()) # now wait until the new thread really started and consumed 'z' willing_to_wait_more = 1000 @@ -147,8 +142,7 @@ state.gil.release() time.sleep(0.005) state.gil.acquire(True) - if we_are_translated(): - llop.gc_thread_run(lltype.Void) + gc_thread_run() def f(): state.gil = allocate_lock_NOAUTO() @@ -168,8 +162,7 @@ state.gil.release() time.sleep(0.01) state.gil.acquire(True) - if we_are_translated(): - llop.gc_thread_run(lltype.Void) + gc_thread_run() state.gil.release() time.sleep(0.1) return len(state.answers) From tverwaes at codespeak.net Tue May 27 20:30:17 2008 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Tue, 27 May 2008 20:30:17 +0200 (CEST) Subject: [pypy-svn] r55317 - in pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk: . test Message-ID: <20080527183017.3878C169EC0@codespeak.net> Author: tverwaes Date: Tue May 27 20:30:13 2008 New Revision: 55317 Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/constants.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/interpreter.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/objspace.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/primitives.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_interpreter.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_miniimage.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_wrapper.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/wrapper.py Log: adding support for Points for the become-test which we compile in test_miniimage Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/constants.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/constants.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/constants.py Tue May 27 20:30:13 2008 @@ -108,7 +108,7 @@ "Float" : SO_FLOAT_CLASS, "MethodContext" : SO_METHODCONTEXT_CLASS, "BlockContext" : SO_BLOCKCONTEXT_CLASS, -# "Point" : SO_POINT_CLASS, + "Point" : SO_POINT_CLASS, # "LargePositiveInteger" : SO_LARGEPOSITIVEINTEGER_CLASS, # "Display" : SO_DISPLAY_CLASS, # "Message" : SO_MESSAGE_CLASS, Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/interpreter.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/interpreter.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/interpreter.py Tue May 27 20:30:13 2008 @@ -441,7 +441,7 @@ self.callPrimitive(primitives.MOD, "\\\\", 1, interp) def bytecodePrimMakePoint(self, interp): - raise MissingBytecode("bytecodePrimMakePoint") + self.callPrimitive(primitives.MAKE_POINT, "@", 1, interp) def bytecodePrimBitShift(self, interp): self.callPrimitive(primitives.BIT_SHIFT, "bitShift:", 1, interp) Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/objspace.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/objspace.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/objspace.py Tue May 27 20:30:13 2008 @@ -106,6 +106,7 @@ define_cls("w_MethodContext", "w_ContextPart") define_cls("w_Link", "w_Object") define_cls("w_Process", "w_Link") + define_cls("w_Point", "w_Object") define_cls("w_LinkedList", "w_SequenceableCollection") define_cls("w_Semaphore", "w_LinkedList") define_cls("w_BlockContext", "w_ContextPart", Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/primitives.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/primitives.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/primitives.py Tue May 27 20:30:13 2008 @@ -280,10 +280,21 @@ w_res = interp.space.wrap_float(math.exp(f)) return w_res +MAKE_POINT = 18 + + at expose_primitive(MAKE_POINT, unwrap_spec=[int, int]) +def func(interp, x, y): + w_res = interp.space.classtable['w_Point'].as_class_get_shadow(interp.space).new(2) + point = wrapper.PointWrapper(interp.space, w_res) + point.store_x(interp.space, x) + point.store_y(interp.space, y) + return w_res + + # ___________________________________________________________________________ # Failure -FAIL = 18 +FAIL = 19 # ___________________________________________________________________________ # Subscript and Stream Primitives Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_interpreter.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_interpreter.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_interpreter.py Tue May 27 20:30:13 2008 @@ -454,6 +454,19 @@ 1, "sub"]], test) +def test_makePoint(): + interp = new_interpreter(pushConstantZeroBytecode + + pushConstantOneBytecode + + bytecodePrimMakePoint) + interp.step() + interp.step() + interp.step() + w_point = interp.s_active_context().top() + from pypy.lang.smalltalk.wrapper import PointWrapper + point = PointWrapper(interp.space, w_point) + assert point.x(interp.space) == 0 + assert point.y(interp.space) == 1 + def test_longJumpIfTrue(): interp = new_interpreter(longJumpIfTrue(0) + chr(15) + longJumpIfTrue(0) + chr(15)) interp.s_active_context().push(space.w_false) Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_miniimage.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_miniimage.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_miniimage.py Tue May 27 20:30:13 2008 @@ -225,7 +225,7 @@ interp = interpreter.Interpreter() interp.store_w_active_context(s_ctx.w_self()) interp.interpret() - + def test_compile_method(): sourcecode = """fib ^self < 2 @@ -234,6 +234,7 @@ perform(w(10).getclass(space), "compile:classified:notifying:", w(sourcecode), w('pypy'), w(None)) assert perform(w(10), "fib").is_same_object(w(89)) + def w(any): # XXX could put this on the space? if any is None: @@ -244,15 +245,40 @@ return space.wrap_chr(any) else: return space.wrap_string(any) - if isinstance(any, int): - return space.wrap_int(any) if isinstance(any, bool): return space.wrap_bool(any) + if isinstance(any, int): + return space.wrap_int(any) if isinstance(any, float): return space.wrap_float(any) else: raise Exception - + +def test_become(): + sourcecode = """ + testBecome + | p1 p2 a | + p1 := 1 at 2. + p2 := #(3 4 5). + a := p1 -> p2. + (1 at 2 = a key) ifFalse: [^false]. + (#(3 4 5) = a value) ifFalse: [^false]. + (p1 -> p2 = a) ifFalse: [^false]. + (p1 == a key) ifFalse: [^false]. + (p2 == a value) ifFalse: [^false]. + p1 become: p2. + (1 at 2 = a value) ifFalse: [^false]. + (#(3 4 5) = a key) ifFalse: [^false]. + (p1 -> p2 = a) ifFalse: [^false]. + (p1 == a key) ifFalse: [^false]. + (p2 == a value) ifFalse: [^false]. + + ^true""" + perform(w(10).getclass(space), "compile:classified:notifying:", w(sourcecode), w('pypy'), w(None)) + w_true = w(True) + w_result = perform(w(10), "testBecome") + w_result.is_same_object(w_true) + def perform(w_receiver, selector, *arguments_w): interp = interpreter.Interpreter(space) s_class = w_receiver.shadow_of_my_class(space) Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_wrapper.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_wrapper.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_wrapper.py Tue May 27 20:30:13 2008 @@ -115,7 +115,7 @@ def new_semaphore(excess_signals=0): w_semaphore = model.W_PointersObject(None, 3) semaphore = wrapper.SemaphoreWrapper(space, w_semaphore) - semaphore.store_excess_signals(space.wrap_int(excess_signals)) + semaphore.store_excess_signals(space, excess_signals) return semaphore @@ -203,9 +203,9 @@ def test_semaphore_excess_signal(self): semaphore = new_semaphore() - - semaphore.signal(None) - assert space.unwrap_int(semaphore.excess_signals()) == 1 + self.space = space + semaphore.signal(self) + assert semaphore.excess_signals(space) == 1 def test_highest_priority(self): py.test.raises(FatalError, wrapper.scheduler(space).highest_priority_process) @@ -227,7 +227,8 @@ def test_semaphore_signal_wait(self): semaphore = new_semaphore() - semaphore.signal(None) + self.space = space + semaphore.signal(self) interp, process, old_process = self.make_processes(4, 2, space.w_false, space.w_true) semaphore.wait(interp) assert semaphore.is_empty_list() Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/wrapper.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/wrapper.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/wrapper.py Tue May 27 20:30:13 2008 @@ -32,7 +32,20 @@ def make_getter_setter(index0): return make_getter(index0), make_setter(index0) - + +def make_int_getter(index0): + def getter(self, space): + return space.unwrap_int(self.read(index0)) + return getter + +def make_int_setter(index0): + def setter(self, space, new): + return self.write(index0, space.wrap_int(new)) + return setter + +def make_int_getter_setter(index0): + return make_int_getter(index0), make_int_setter(index0) + class LinkWrapper(Wrapper): next_link, store_next_link = make_getter_setter(0) @@ -169,23 +182,43 @@ class SemaphoreWrapper(LinkedListWrapper): - excess_signals, store_excess_signals = make_getter_setter(2) + excess_signals, store_excess_signals = make_int_getter_setter(2) def signal(self, interp): if self.is_empty_list(): - w_value = self.excess_signals() - w_value = self.space.wrap_int(self.space.unwrap_int(w_value) + 1) - self.store_excess_signals(w_value) + value = self.excess_signals(interp.space) + self.store_excess_signals(interp.space, value + 1) else: process = self.remove_first_link_of_list() ProcessWrapper(self.space, process).resume(interp) def wait(self, interp): - excess = self.space.unwrap_int(self.excess_signals()) + excess = self.excess_signals(interp.space) w_process = scheduler(interp.space).active_process() if excess > 0: - w_excess = self.space.wrap_int(excess - 1) - self.store_excess_signals(w_excess) + self.store_excess_signals(interp.space, excess - 1) else: self.add_last_link(w_process) ProcessWrapper(self.space, w_process).suspend(interp) + +class PointWrapper(Wrapper): + x, store_x = make_int_getter_setter(0) + y, store_y = make_int_getter_setter(1) + +# XXX Wrappers below are not used yet. +class OffsetWrapper(Wrapper): + offset_x = make_int_getter(0) + offset_y = make_int_setter(1) + +class MaskWrapper(Wrapper): + bits = make_getter(0) + extend_x = make_int_getter(1) + extend_y = make_int_getter(2) + depth = make_int_getter(3) + +class CursorWrapper(MaskWrapper): + offset = make_getter(4) + +class PointWrapper(Wrapper): + x, store_x = make_int_getter_setter(0) + y, store_y = make_int_getter_setter(1) From arigo at codespeak.net Tue May 27 22:16:20 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 27 May 2008 22:16:20 +0200 (CEST) Subject: [pypy-svn] r55319 - in pypy/branch/gc+thread/pypy: interpreter module/thread module/thread/test rpython/lltypesystem Message-ID: <20080527201620.1334C4981C6@codespeak.net> Author: arigo Date: Tue May 27 22:16:18 2008 New Revision: 55319 Modified: pypy/branch/gc+thread/pypy/interpreter/miscutils.py pypy/branch/gc+thread/pypy/module/thread/gil.py pypy/branch/gc+thread/pypy/module/thread/ll_thread.py pypy/branch/gc+thread/pypy/module/thread/test/support.py pypy/branch/gc+thread/pypy/module/thread/test/test_ll_thread.py pypy/branch/gc+thread/pypy/module/thread/threadlocals.py pypy/branch/gc+thread/pypy/rpython/lltypesystem/rffi.py Log: It's all slightly delicate, but overall it looks like progress, maybe. Modified: pypy/branch/gc+thread/pypy/interpreter/miscutils.py ============================================================================== --- pypy/branch/gc+thread/pypy/interpreter/miscutils.py (original) +++ pypy/branch/gc+thread/pypy/interpreter/miscutils.py Tue May 27 22:16:18 2008 @@ -168,9 +168,6 @@ def getmainthreadvalue(self): return self._value - def getGIL(self): - return None # XXX temporary hack! - class Action(object): """Abstract base class for actions that must be performed regularly, Modified: pypy/branch/gc+thread/pypy/module/thread/gil.py ============================================================================== --- pypy/branch/gc+thread/pypy/module/thread/gil.py (original) +++ pypy/branch/gc+thread/pypy/module/thread/gil.py Tue May 27 22:16:18 2008 @@ -16,16 +16,16 @@ class GILThreadLocals(OSThreadLocals): """A version of OSThreadLocals that enforces a GIL.""" - GIL = None + ll_GIL = None def setup_threads(self, space): """Enable threads in the object space, if they haven't already been.""" - if self.GIL is None: + if self.ll_GIL is None: try: - self.GIL = thread.allocate_lock_NOAUTO() + self.ll_GIL = thread.allocate_ll_lock() except thread.error: raise wrap_thread_error(space, "can't allocate GIL") - self.GIL.acquire(True) + thread.acquire_NOAUTO(self.ll_GIL, True) self.enter_thread(space) # setup the main thread # add the GIL-releasing callback as an action on the space space.pending_actions.append(GILReleaseAction(self)) @@ -41,23 +41,20 @@ # test_lock_again after the global state was cleared by # test_compile_lock. As a workaround, we repatch these global # fields systematically. - spacestate.GIL = self.GIL + spacestate.ll_GIL = self.ll_GIL invoke_around_extcall(before_external_call, after_external_call) return result def yield_thread(self): """Notification that the current thread is between two bytecodes: release the GIL for a little while.""" - GIL = self.GIL + ll_GIL = self.ll_GIL # Other threads can run between the release() and the acquire(). # This is a single external function so that we are sure that nothing # occurs between the release and the acquire, e.g. no GC operation. - GIL.fused_release_acquire() + thread.fused_release_acquire_NOAUTO(ll_GIL) thread.gc_thread_run() - def getGIL(self): - return self.GIL # XXX temporary hack! - class GILReleaseAction(Action): """An action called when the current thread is between two bytecodes @@ -82,11 +79,11 @@ # this function must not raise, in such a way that the exception # transformer knows that it cannot raise! e = get_errno() - spacestate.GIL.release() + thread.release_NOAUTO(spacestate.ll_GIL) set_errno(e) def after_external_call(): e = get_errno() - spacestate.GIL.acquire(True) + thread.acquire_NOAUTO(spacestate.ll_GIL, True) thread.gc_thread_run() set_errno(e) Modified: pypy/branch/gc+thread/pypy/module/thread/ll_thread.py ============================================================================== --- pypy/branch/gc+thread/pypy/module/thread/ll_thread.py (original) +++ pypy/branch/gc+thread/pypy/module/thread/ll_thread.py Tue May 27 22:16:18 2008 @@ -31,13 +31,23 @@ ) def llexternal(name, args, result, **kwds): + kwds.setdefault('sandboxsafe', True) return rffi.llexternal(name, args, result, compilation_info=eci, **kwds) def _emulated_start_new_thread(func): + "NOT_RPYTHON" import thread + def runner(): + if rffi.aroundstate.after: + rffi.aroundstate.after() + try: + func() + finally: + if rffi.aroundstate.before: + rffi.aroundstate.before() try: - ident = thread.start_new_thread(func, ()) + ident = thread.start_new_thread(runner, ()) except thread.error: ident = -1 return rffi.cast(rffi.INT, ident) @@ -45,43 +55,33 @@ CALLBACK = lltype.Ptr(lltype.FuncType([], lltype.Void)) c_thread_start = llexternal('RPyThreadStart', [CALLBACK], rffi.INT, _callable=_emulated_start_new_thread) -c_thread_get_ident = llexternal('RPyThreadGetIdent', [], rffi.INT) +c_thread_get_ident = llexternal('RPyThreadGetIdent', [], rffi.INT, + _nowrapper=True) # always call directly TLOCKP = rffi.COpaquePtr('struct RPyOpaque_ThreadLock', compilation_info=eci) c_thread_lock_init = llexternal('RPyThreadLockInit', [TLOCKP], lltype.Void) c_thread_acquirelock = llexternal('RPyThreadAcquireLock', [TLOCKP, rffi.INT], - rffi.INT) -c_thread_releaselock = llexternal('RPyThreadReleaseLock', [TLOCKP], lltype.Void) + rffi.INT, + threadsafe=True) # release the GIL +c_thread_releaselock = llexternal('RPyThreadReleaseLock', [TLOCKP], lltype.Void, + threadsafe=True) # release the GIL # another set of functions, this time in versions that don't cause the # GIL to be released. To use to handle the GIL lock itself. c_thread_acquirelock_NOAUTO = llexternal('RPyThreadAcquireLock', [TLOCKP, rffi.INT], rffi.INT, - threadsafe=False) + _nowrapper=True) c_thread_releaselock_NOAUTO = llexternal('RPyThreadReleaseLock', [TLOCKP], lltype.Void, - threadsafe=False) + _nowrapper=True) c_thread_fused_releaseacquirelock_NOAUTO = llexternal( 'RPyThreadFusedReleaseAcquireLock', [TLOCKP], lltype.Void, - threadsafe=False) + _nowrapper=True) def allocate_lock(): - ll_lock = lltype.malloc(TLOCKP.TO, flavor='raw') - res = c_thread_lock_init(ll_lock) - if res == -1: - lltype.free(ll_lock, flavor='raw') - raise error("out of resources") - return Lock(ll_lock) - -def allocate_lock_NOAUTO(): - ll_lock = lltype.malloc(TLOCKP.TO, flavor='raw') - res = c_thread_lock_init(ll_lock) - if res == -1: - lltype.free(ll_lock, flavor='raw') - raise error("out of resources") - return Lock_NOAUTO(ll_lock) + return Lock(allocate_ll_lock()) def ll_start_new_thread(func): ident = c_thread_start(func) @@ -123,26 +123,31 @@ def __del__(self): lltype.free(self._lock, flavor='raw') -class Lock_NOAUTO(object): - """A special lock that doesn't cause the GIL to be released when - we try to acquire it. Used for the GIL itself.""" - - def __init__(self, ll_lock): - self._lock = ll_lock - - def acquire(self, flag): - return bool(c_thread_acquirelock_NOAUTO(self._lock, int(flag))) - - def release(self): - ll_assert(not self.acquire(False), "Lock_NOAUTO was not held!") - c_thread_releaselock_NOAUTO(self._lock) +# ____________________________________________________________ +# +# GIL support wrappers - def fused_release_acquire(self): - ll_assert(not self.acquire(False), "Lock_NOAUTO was not held!") - c_thread_fused_releaseacquirelock_NOAUTO(self._lock) +def allocate_ll_lock(): + ll_lock = lltype.malloc(TLOCKP.TO, flavor='raw') + res = c_thread_lock_init(ll_lock) + if res == -1: + lltype.free(ll_lock, flavor='raw') + raise error("out of resources") + return ll_lock - def __del__(self): - lltype.free(self._lock, flavor='raw') +def acquire_NOAUTO(ll_lock, flag): + flag = rffi.cast(rffi.INT, flag) + return bool(c_thread_acquirelock_NOAUTO(ll_lock, flag)) + +def release_NOAUTO(ll_lock): + if not we_are_translated(): + ll_assert(not acquire_NOAUTO(ll_lock, False), "NOAUTO lock not held!") + c_thread_releaselock_NOAUTO(ll_lock) + +def fused_release_acquire_NOAUTO(ll_lock): + if not we_are_translated(): + ll_assert(not acquire_NOAUTO(ll_lock, False), "NOAUTO lock not held!") + c_thread_fused_releaseacquirelock_NOAUTO(ll_lock) # ____________________________________________________________ # @@ -164,6 +169,7 @@ """ if we_are_translated(): llop.gc_thread_run(lltype.Void) +gc_thread_run._always_inline_ = True def gc_thread_die(): """To call just before the final GIL release done by a dying @@ -172,3 +178,4 @@ """ if we_are_translated(): llop.gc_thread_die(lltype.Void) +gc_thread_die._always_inline_ = True Modified: pypy/branch/gc+thread/pypy/module/thread/test/support.py ============================================================================== --- pypy/branch/gc+thread/pypy/module/thread/test/support.py (original) +++ pypy/branch/gc+thread/pypy/module/thread/test/support.py Tue May 27 22:16:18 2008 @@ -2,6 +2,7 @@ import time, gc from pypy.conftest import gettestobjspace, option from pypy.interpreter.gateway import ObjSpace, W_Root, interp2app_temp +from pypy.module.thread import gil NORMAL_TIMEOUT = 300.0 # 5 minutes @@ -10,10 +11,9 @@ adaptivedelay = 0.04 limit = time.time() + delay * NORMAL_TIMEOUT while time.time() <= limit: - GIL = space.threadlocals.GIL - GIL.release() + gil.before_external_call() time.sleep(adaptivedelay) - GIL.acquire(True) + gil.after_external_call() gc.collect() if space.is_true(space.call_function(w_condition)): return Modified: pypy/branch/gc+thread/pypy/module/thread/test/test_ll_thread.py ============================================================================== --- pypy/branch/gc+thread/pypy/module/thread/test/test_ll_thread.py (original) +++ pypy/branch/gc+thread/pypy/module/thread/test/test_ll_thread.py Tue May 27 22:16:18 2008 @@ -29,13 +29,13 @@ py.test.fail("Did not raise") def test_fused(): - l = allocate_lock_NOAUTO() - l.acquire(True) - l.fused_release_acquire() - could_acquire_again = l.acquire(False) + l = allocate_ll_lock() + acquire_NOAUTO(l, True) + fused_release_acquire_NOAUTO(l) + could_acquire_again = acquire_NOAUTO(l, False) assert not could_acquire_again - l.release() - could_acquire_again = l.acquire(False) + release_NOAUTO(l) + could_acquire_again = acquire_NOAUTO(l, False) assert could_acquire_again @@ -122,13 +122,13 @@ run._dont_inline_ = True def bootstrap(): - state.gil.acquire(True) + acquire_NOAUTO(state.gil, True) gc_thread_run() z = state.z state.z = None z.run() gc_thread_die() - state.gil.release() + release_NOAUTO(state.gil) def g(i, j): state.z = Z(i, j) @@ -139,14 +139,14 @@ while state.z is not None: assert willing_to_wait_more > 0 willing_to_wait_more -= 1 - state.gil.release() + release_NOAUTO(state.gil) time.sleep(0.005) - state.gil.acquire(True) + acquire_NOAUTO(state.gil, True) gc_thread_run() def f(): - state.gil = allocate_lock_NOAUTO() - state.gil.acquire(True) + state.gil = allocate_ll_lock() + acquire_NOAUTO(state.gil, True) state.answers = [] state.finished = 0 g(7, 1) @@ -159,11 +159,11 @@ expected)) willing_to_wait_more -= 1 done = len(state.answers) == expected - state.gil.release() + release_NOAUTO(state.gil) time.sleep(0.01) - state.gil.acquire(True) + acquire_NOAUTO(state.gil, True) gc_thread_run() - state.gil.release() + release_NOAUTO(state.gil) time.sleep(0.1) return len(state.answers) Modified: pypy/branch/gc+thread/pypy/module/thread/threadlocals.py ============================================================================== --- pypy/branch/gc+thread/pypy/module/thread/threadlocals.py (original) +++ pypy/branch/gc+thread/pypy/module/thread/threadlocals.py Tue May 27 22:16:18 2008 @@ -52,7 +52,3 @@ def atthreadexit(self, space, exit_func, w_obj): ec = space.getexecutioncontext() ec.thread_exit_funcs.append((exit_func, w_obj)) - - def getGIL(self): - return None - Modified: pypy/branch/gc+thread/pypy/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/branch/gc+thread/pypy/rpython/lltypesystem/rffi.py (original) +++ pypy/branch/gc+thread/pypy/rpython/lltypesystem/rffi.py Tue May 27 22:16:18 2008 @@ -192,6 +192,9 @@ os.write(2, "Warning: uncaught exception in callback: %%s %%s\n" %% (callable_name, str(e))) + if not we_are_translated(): + import traceback + traceback.print_exc() result = errorcode if before: before() @@ -203,6 +206,7 @@ miniglobals = locals().copy() miniglobals['Exception'] = Exception miniglobals['os'] = os + miniglobals['we_are_translated'] = we_are_translated exec source.compile() in miniglobals return miniglobals['wrapper'] _make_wrapper_for._annspecialcase_ = 'specialize:memo' From arigo at codespeak.net Tue May 27 22:40:53 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 27 May 2008 22:40:53 +0200 (CEST) Subject: [pypy-svn] r55320 - pypy/branch/gc+thread/pypy/module/thread Message-ID: <20080527204053.A5D7B168520@codespeak.net> Author: arigo Date: Tue May 27 22:40:50 2008 New Revision: 55320 Modified: pypy/branch/gc+thread/pypy/module/thread/gil.py pypy/branch/gc+thread/pypy/module/thread/ll_thread.py Log: Translation fixes. Modified: pypy/branch/gc+thread/pypy/module/thread/gil.py ============================================================================== --- pypy/branch/gc+thread/pypy/module/thread/gil.py (original) +++ pypy/branch/gc+thread/pypy/module/thread/gil.py Tue May 27 22:40:50 2008 @@ -16,11 +16,11 @@ class GILThreadLocals(OSThreadLocals): """A version of OSThreadLocals that enforces a GIL.""" - ll_GIL = None + ll_GIL = thread.null_ll_lock def setup_threads(self, space): """Enable threads in the object space, if they haven't already been.""" - if self.ll_GIL is None: + if not self.ll_GIL: try: self.ll_GIL = thread.allocate_ll_lock() except thread.error: Modified: pypy/branch/gc+thread/pypy/module/thread/ll_thread.py ============================================================================== --- pypy/branch/gc+thread/pypy/module/thread/ll_thread.py (original) +++ pypy/branch/gc+thread/pypy/module/thread/ll_thread.py Tue May 27 22:40:50 2008 @@ -110,7 +110,9 @@ self._lock = ll_lock def acquire(self, flag): - return bool(c_thread_acquirelock(self._lock, int(flag))) + res = c_thread_acquirelock(self._lock, int(flag)) + res = rffi.cast(lltype.Signed, res) + return bool(res) def release(self): # Sanity check: the lock must be locked @@ -127,6 +129,8 @@ # # GIL support wrappers +null_ll_lock = lltype.nullptr(TLOCKP.TO) + def allocate_ll_lock(): ll_lock = lltype.malloc(TLOCKP.TO, flavor='raw') res = c_thread_lock_init(ll_lock) @@ -136,8 +140,10 @@ return ll_lock def acquire_NOAUTO(ll_lock, flag): - flag = rffi.cast(rffi.INT, flag) - return bool(c_thread_acquirelock_NOAUTO(ll_lock, flag)) + flag = rffi.cast(rffi.INT, int(flag)) + res = c_thread_acquirelock_NOAUTO(ll_lock, flag) + res = rffi.cast(lltype.Signed, res) + return bool(res) def release_NOAUTO(ll_lock): if not we_are_translated(): From afa at codespeak.net Tue May 27 23:06:31 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 27 May 2008 23:06:31 +0200 (CEST) Subject: [pypy-svn] r55321 - pypy/branch/win32port Message-ID: <20080527210631.EB366698061@codespeak.net> Author: afa Date: Tue May 27 23:06:30 2008 New Revision: 55321 Removed: pypy/branch/win32port/ Log: Remove merged branch From afa at codespeak.net Tue May 27 23:07:35 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Tue, 27 May 2008 23:07:35 +0200 (CEST) Subject: [pypy-svn] r55322 - pypy/branch/build-external Message-ID: <20080527210735.519F0698061@codespeak.net> Author: afa Date: Tue May 27 23:07:34 2008 New Revision: 55322 Added: pypy/branch/build-external/ - copied from r55321, pypy/dist/ Log: Branch to try to compile external dependencies from sources From cami at codespeak.net Tue May 27 23:10:11 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Tue, 27 May 2008 23:10:11 +0200 (CEST) Subject: [pypy-svn] r55323 - in pypy/dist/pypy/lang/gameboy: . test Message-ID: <20080527211011.78485698061@codespeak.net> Author: cami Date: Tue May 27 23:10:10 2008 New Revision: 55323 Modified: pypy/dist/pypy/lang/gameboy/cartridge.py pypy/dist/pypy/lang/gameboy/cpu.py pypy/dist/pypy/lang/gameboy/gameboy.py pypy/dist/pypy/lang/gameboy/gameboyImplementation.py pypy/dist/pypy/lang/gameboy/joypad.py pypy/dist/pypy/lang/gameboy/ram.py pypy/dist/pypy/lang/gameboy/test/test_memory_bank_controller.py pypy/dist/pypy/lang/gameboy/test/test_video.py pypy/dist/pypy/lang/gameboy/timer.py pypy/dist/pypy/lang/gameboy/video.py Log: added more tests for the video driver made som buggy refactoring in the cartridge, "gameplay" not affected Modified: pypy/dist/pypy/lang/gameboy/cartridge.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/cartridge.py (original) +++ pypy/dist/pypy/lang/gameboy/cartridge.py Tue May 27 23:10:10 2008 @@ -7,18 +7,22 @@ from pypy.lang.gameboy.ram import iMemory +import math + #from pypy.rlib.rstr import str_replace import os +# HELPERS ---------------------------------------------------------------------- + def has_cartridge_battery(self, cartridge_type): - return (cartridge_type == constants.TYPE_MBC1_RAM_BATTERY \ - or cartridge_type == constants.TYPE_MBC2_BATTERY \ - or cartridge_type == constants.TYPE_MBC3_RTC_BATTERY \ - or cartridge_type == constants.TYPE_MBC3_RTC_RAM_BATTERY \ - or cartridge_type == constants.TYPE_MBC3_RAM_BATTERY \ - or cartridge_type == constants.TYPE_MBC5_RAM_BATTERY \ - or cartridge_type == constants.TYPE_MBC5_RUMBLE_RAM_BATTERY \ + return (cartridge_type == constants.TYPE_MBC1_RAM_BATTERY + or cartridge_type == constants.TYPE_MBC2_BATTERY + or cartridge_type == constants.TYPE_MBC3_RTC_BATTERY + or cartridge_type == constants.TYPE_MBC3_RTC_RAM_BATTERY + or cartridge_type == constants.TYPE_MBC3_RAM_BATTERY + or cartridge_type == constants.TYPE_MBC5_RAM_BATTERY + or cartridge_type == constants.TYPE_MBC5_RUMBLE_RAM_BATTERY or cartridge_type == constants.TYPE_HUC1_RAM_BATTERY) @@ -28,13 +32,10 @@ else: raise InvalidMemoryBankTypeError("Unsupported memory bank controller (0x"+hex(cartridge_type)+")") -class InvalidMemoryBankTypeError(Exception): - pass - def map_to_byte( string): mapped = [0]*len(string) for i in range(len(string)): - mapped[i] = ord(string[i]) & 0xFF + mapped[i] = ord(string[i]) return mapped def map_to_string(int_array): @@ -42,6 +43,24 @@ for i in range(len(int_array)): mapped[i] = chr(int_array[i]) return ("").join(mapped) + +# EXCEPIONS -------------------------------------------------------------------- + +class InvalidMemoryBankTypeError(Exception): + pass + +class InvalidMemoryAccessException(Exception): + pass + +class InvalidSizeException(Exception): + pass + +class CartridgeHeaderCorruptedException(Exception): + pass + +class CartridgeTruncatedException(Exception): + pass + # ============================================================================== # CARTRIDGE @@ -56,7 +75,7 @@ def reset(self): if not self.has_battery(): - self.ram[0:len(self.ram):1] = 0xFF + self.ram = [0xFF]*len(self.ram) self.mbc.reset() def read(self, address): @@ -68,19 +87,19 @@ def load(self, cartridge, verify=True): assert isinstance(cartridge, CartridgeFile) self.cartridge = cartridge - self.rom = self.cartridge.read() + self.rom = self.cartridge.read() if verify: self.check_rom() self.create_ram() self.load_battery() - self.mbc = self.create_bank_controller(self.get_memory_bank_type(), \ + self.mbc = self.create_bank_controller(self.get_memory_bank_type(), self.rom, self.ram, self.clock) def check_rom(self): if not self.verify_header(): - raise Exception("Cartridge header is corrupted") + raise CartridgeHeaderCorruptedException("Cartridge Header is corrupted") if self.cartridge.get_size() < self.get_rom_size(): - raise Exception("Cartridge is truncated") + raise CartridgeTruncatedException("Cartridge is truncated") def create_ram(self): ram_size = self.get_ram_size() @@ -98,7 +117,7 @@ self.cartridge.write_battery(self.ram) def get_memory_bank_type(self): - return self.rom[constants.CARTRIDGE_TYPE_ADDRESS] & 0xFF + return self.rom[constants.CARTRIDGE_TYPE_ADDRESS] def get_memory_bank(self): return self.mbc @@ -107,29 +126,30 @@ return self.rom def get_rom_size(self): - rom_size = self.rom[constants.CARTRIDGE_ROM_SIZE_ADDRESS] & 0xFF + rom_size = self.rom[constants.CARTRIDGE_ROM_SIZE_ADDRESS] if rom_size>=0x00 and rom_size<=0x07: return 32768 << rom_size return -1 def get_ram_size(self): - return constants.CARTRIDGE_RAM_SIZE_MAPPING[self.rom[constants.CARTRIDGE_RAM_SIZE_ADDRESS]] + return constants.CARTRIDGE_RAM_SIZE_MAPPING[ + self.rom[constants.CARTRIDGE_RAM_SIZE_ADDRESS]] def get_destination_code(self): - return self.rom[constants.DESTINATION_CODE_ADDRESS] & 0xFF + return self.rom[constants.DESTINATION_CODE_ADDRESS] def get_licensee_code(): - return self.rom[constants.LICENSEE_ADDRESS] & 0xFF + return self.rom[constants.LICENSEE_ADDRESS] def get_rom_version(self): - return self.rom[constants.CARTRIDGE_ROM_VERSION_ADDRESS] & 0xFF + return self.rom[constants.CARTRIDGE_ROM_VERSION_ADDRESS] def get_header_checksum(self): - return self.rom[constants.HEADER_CHECKSUM_ADDRESS] & 0xFF + return self.rom[constants.HEADER_CHECKSUM_ADDRESS] def get_checksum(self): - return ((self.rom[constants.CHECKSUM_A_ADDRESS] & 0xFF) << 8) \ - + (self.rom[constants.CHECKSUM_B_ADDRESS] & 0xFF) + return ((self.rom[constants.CHECKSUM_A_ADDRESS]) << 8) \ + + (self.rom[constants.CHECKSUM_B_ADDRESS]) def has_battery(self): return has_cartridge_battery(self.get_memory_bank_type()) @@ -138,7 +158,7 @@ checksum = 0 for address in range(len(self.rom)): if address is not 0x014E and address is not 0x014F: - checksum = (checksum + (self.rom[address] & 0xFF)) & 0xFFFF + checksum = (checksum + (self.rom[address])) & 0xFF return (checksum == self.get_checksum()) def verify_header(self): @@ -146,7 +166,7 @@ return False checksum = 0xE7 for address in range(0x0134, 0x014C): - checksum = (checksum - (self.rom[address] & 0xFF)) & 0xFF + checksum = (checksum - (self.rom[address])) & 0xFF return (checksum == self.get_header_checksum()) def create_bank_controller(self, type, rom, ram, clock_driver): @@ -166,32 +186,32 @@ self.load(file) def reset(self): - self.cartridge_name = "" - self.cartridge_file_path = "" - self.cartridge_stream = None + self.cartridge_name = "" + self.cartridge_file_path = "" + self.cartridge_stream = None self.cartridge_file_contents = None - self.battery_name = "" - self.battery_file_path = "" - self.battery_stream = None - self.battery_file_contents = None + self.battery_name = "" + self.battery_file_path = "" + self.battery_stream = None + self.battery_file_contents = None def load(self, cartridge_path): - if cartridge_path is None: - raise Exception("cartridge_path cannot be None!") cartridge_path = str(cartridge_path) self.cartridge_file_path = cartridge_path self.cartridge_stream = open_file_as_stream(cartridge_path) - self.cartridge_file_contents = map_to_byte( \ + self.cartridge_file_contents = map_to_byte( self.cartridge_stream.readall()) self.load_battery(cartridge_path) def load_battery(self, cartridge_file_path): self.battery_file_path = self.create_battery_file_path(cartridge_file_path) if self.has_battery(): - self.battery_stream = open_file_as_stream(self.battery_file_path) - self.battery_file_contents = map_to_byte( \ - self.battery_stream.readall()) + self.read_battery() + + def read_battery(self): + self.battery_stream = open_file_as_stream(self.battery_file_path) + self.battery_file_contents = map_to_byte(self.battery_stream.readall()) def create_battery_file_path(self, cartridge_file_path): if cartridge_file_path.endswith(constants.CARTRIDGE_FILE_EXTENSION): @@ -213,7 +233,7 @@ return self.cartridge_file_contents def read_battery(self): - return self.battery_file_contents + return self.battery_file_contents def write_battery(self, ram): output_stream = open_file_as_stream(self.battery_file_path, "w") @@ -242,18 +262,20 @@ def __init__(self, rom, ram, clock_driver, min_rom_bank_size=0, max_rom_bank_size=0, - min_ram_bank_size=0, max_ram_bank_size=0): + min_ram_bank_size=0, max_ram_bank_size=0, + rom_bank_size=constants.ROM_BANK_SIZE): self.clock = clock_driver self.min_rom_bank_size = min_rom_bank_size self.max_rom_bank_size = max_rom_bank_size self.min_ram_bank_size = min_ram_bank_size self.max_ram_bank_size = max_ram_bank_size + self.rom_bank_size = rom_bank_size + self.rom_bank = self.rom_bank_size self.reset() self.set_rom(rom) self.set_ram(ram) def reset(self): - self.rom_bank = constants.ROM_BANK_SIZE self.ram_bank = 0 self.ram_enable = False self.rom = [] @@ -262,39 +284,45 @@ self.ram_size = 0 def set_rom(self, buffer): - banks = int(len(buffer) / constants.ROM_BANK_SIZE) + banks = int(len(buffer) / self.rom_bank_size) if banks < self.min_rom_bank_size or banks > self.max_rom_bank_size: - raise Exception("Invalid ROM size %s, should be in [%s %s]" % \ - (hex(banks), hex(self.min_rom_bank_size), \ + raise InvalidSizeException("Invalid ROM size %s, should be in [%s %s]" % + (hex(banks), hex(self.min_rom_bank_size), hex(self.max_rom_bank_size))) - self.rom = buffer - self.rom_size = constants.ROM_BANK_SIZE * banks - 1 + self.rom = buffer + self.rom_size = self.rom_bank_size * banks - 1 def set_ram(self, buffer): banks = int(len(buffer) / constants.RAM_BANK_SIZE) if banks < self.min_ram_bank_size or banks > self.max_ram_bank_size: - raise Exception("Invalid RAM size %s, should be in [%s %s]" % \ - (hex(banks), hex(self.min_ram_bank_size), \ + raise InvalidSizeException("Invalid RAM size %s, should be in [%s %s]" % + (hex(banks), hex(self.min_ram_bank_size), hex(self.max_ram_bank_size))) - self.ram = buffer + self.ram = buffer self.ram_size = constants.RAM_BANK_SIZE * banks - 1 - def read(self, address): - if address <= 0x3FFF: # 0000-3FFF - return self.rom[address] & 0xFF - elif address <= 0x7FFF:# 4000-7FFF - return self.rom[self.rom_bank + (address & 0x3FFF)] & 0xFF - elif address >= 0xA000 and address <= 0xBFFF: # A000-BFFF + def read(self, address): + # 0000-3FFF + if address <= 0x3FFF: + return self.rom[address] + # 4000-7FFF + elif address <= 0x7FFF: + return self.rom[self.rom_bank + (address & 0x3FFF)] + # A000-BFFF + elif address >= 0xA000 and address <= 0xBFFF: if self.ram_enable: - return self.ram[self.ram_bank + (address & 0x1FFF)] & 0xFF + return self.ram[self.ram_bank + (address & 0x1FFF)] else: + #return 0xFF raise Exception("RAM is not Enabled") - raise Exception("MBC: Invalid address, out of range: %s" % hex(address)) + #return 0xFF + raise InvalidMemoryAccessException("MBC: Invalid address, out of range: %s" + % hex(address)) def write(self, address, data): - raise Exception("MBC: Invalid write access") + raise InvalidMemoryAccessException("MBC: Invalid write access") def write_ram_enable(self, address, data): if self.ram_size > 0: @@ -324,7 +352,7 @@ """ PyBoy GameBoy (TM) Emulator - Memory Bank Controller 1 (2MB constants.ROM, 32KB constants.RAM) + Memory Bank Controller 1 (2MB ROM, 32KB RAM) 0000-3FFF ROM Bank 0 (16KB) 4000-7FFF ROM Bank 1-127 (16KB) @@ -342,30 +370,39 @@ self.memory_model = 0 def write(self, address, data): - if address <= 0x1FFF: # 0000-1FFF + # 0000-1FFF + if address <= 0x1FFF: self.write_ram_enable(address, data) - elif address <= 0x3FFF: # 2000-3FFF + # 2000-3FFF + elif address <= 0x3FFF: self.write_rom_bank_1(address, data) - elif address <= 0x5FFF: # 4000-5FFF + # 4000-5FFF + elif address <= 0x5FFF: self.write_rom_bank_2(address, data) - elif address <= 0x7FFF: # 6000-7FFF + # 6000-7FFF + elif address <= 0x7FFF: self.memory_model = data & 0x01 - elif address >= 0xA000 and address <= 0xBFFF and self.ram_enable: # A000-BFFF + # A000-BFFF + elif address >= 0xA000 and address <= 0xBFFF and self.ram_enable: self.ram[self.ram_bank + (address & 0x1FFF)] = data else: - raise Exception("Invalid memory Access address: %s" % hex(address)) + #return + raise InvalidMemoryAccessException("MBC 1Invalid memory Access address: %s" + % hex(address)) def write_rom_bank_1(self, address, data): if (data & 0x1F) == 0: data = 1 if self.memory_model == 0: - self.rom_bank = ((self.rom_bank & 0x180000) + ((data & 0x1F) << 14)) & self.rom_size + self.rom_bank = ((self.rom_bank & 0x180000) + + ((data & 0x1F) << 14)) & self.rom_size else: self.rom_bank = ((data & 0x1F) << 14) & self.rom_size def write_rom_bank_2(self, address, data): if self.memory_model == 0: - self.rom_bank = ((self.rom_bank & 0x07FFFF) + ((data & 0x03) << 19)) & self.rom_size + self.rom_bank = ((self.rom_bank & 0x07FFFF) + + ((data & 0x03) << 19)) & self.rom_size else: self.ram_bank = ((data & 0x03) << 13) & self.ram_size @@ -377,42 +414,43 @@ """ PyBoy GameBoy (TM) Emulator - Memory Bank Controller 2 (256KB constants.ROM, 512x4bit constants.RAM) + Memory Bank Controller 2 (256KB ROM, 512x4bit RAM) 0000-3FFF ROM Bank 0 (16KB) 4000-7FFF ROM Bank 1-15 (16KB) A000-A1FF RAM Bank (512x4bit) """ - RAM_BANK_SIZE = 512 - def __init__(self, rom, ram, clock_driver): MBC.__init__(self, rom, ram, clock_driver, - min_ram_bank_size=1, - max_ram_bank_size=1, - min_rom_bank_size=2, - max_rom_bank_size=16) + min_ram_bank_size=1, max_ram_bank_size=1, + min_rom_bank_size=2, max_rom_bank_size=16, + rom_bank_size=512) - def read(self, address): if address > 0xA1FF: - raise Exception("MBC2 out of Bounds: %s" % hex(address)) + raise InvalidMemoryAccessException("MBC2 out of Bounds: %s" + % hex(address)) elif address >= 0xA000: return self.ram[address & 0x01FF] - elif address >= 0xA000 and address <= 0xA1FF: # A000-BFFF + # A000-BFFF + elif address >= 0xA000 and address <= 0xA1FF: if self.ram_enable: - return self.ram[self.ram_bank + (address & 0x1FFF)] & 0xFF + return self.ram[self.ram_bank + (address & 0x1FFF)] else: raise Exception("RAM is not Enabled") else: return MBC.read(self, address) def write(self, address, data): - if address <= 0x1FFF: # 0000-1FFF + # 0000-1FFF + if address <= 0x1FFF: self.write_ram_enable(address, data) - elif address <= 0x3FFF: # 2000-3FFF + # 2000-3FFF + elif address <= 0x3FFF: self.write_rom_bank(address, data) - elif address >= 0xA000 and address <= 0xA1FF: # A000-A1FF + # A000-A1FF + elif address >= 0xA000 and address <= 0xA1FF: self.write_ram(address, data) def write_rom_bank(self, address, data): @@ -437,12 +475,13 @@ """ PyBoy GameBoy (TM) Emulator - Memory Bank Controller 3 (2MB constants.ROM, 32KB constants.RAM, Real Time Clock) + Memory Bank Controller 3 (2MB ROM, 32KB RAM, Real Time Clock) 0000-3FFF ROM Bank 0 (16KB) 4000-7FFF ROM Bank 1-127 (16KB) A000-BFFF RAM Bank 0-3 (8KB) """ + def __init__(self, rom, ram, clock_driver): MBC.__init__(self, rom, ram, clock_driver, min_ram_bank_size=0, @@ -450,7 +489,6 @@ min_rom_bank_size=2, max_rom_bank_size=128) - def reset(self): MBC.reset(self) self.clock_latched_daysclock_latched_control = None @@ -468,11 +506,11 @@ self.clock_latched_days = 0 self.clock_latched_control = 0 - def read(self, address): - if address >= 0xA000 and address <= 0xBFFF: # A000-BFFF + # A000-BFFF + if address >= 0xA000 and address <= 0xBFFF: if self.ram_bank >= 0: - return self.ram[self.ram_bank + (address & 0x1FFF)] & 0xFF + return self.ram[self.ram_bank + (address & 0x1FFF)] else: return self.read_clock_data(address) else: @@ -489,18 +527,23 @@ return self.clock_latched_days if self.clock_register == 0x0C: return self.clock_latched_control - raise Exception("MBC*.read_clock_data invalid address %i") + raise InvalidMemoryAccessException("MBC3.read_clock_data invalid address %i") def write(self, address, data): - if address <= 0x1FFF: # 0000-1FFF + # 0000-1FFF + if address <= 0x1FFF: self.write_ram_enable(address, data) - elif address <= 0x3FFF: # 2000-3FFF + # 2000-3FFF + elif address <= 0x3FFF: self.write_rom_bank(address, data) - elif address <= 0x5FFF: # 4000-5FFF + # 4000-5FFF + elif address <= 0x5FFF: self.write_ram_bank(address, data) - elif address <= 0x7FFF: # 6000-7FFF + # 6000-7FFF + elif address <= 0x7FFF: self.write_clock_latch(address, data) - elif address >= 0xA000 and address <= 0xBFFF and self.ram_enable: # A000-BFFF + # A000-BFFF + elif address >= 0xA000 and address <= 0xBFFF and self.ram_enable: if self.ram_bank >= 0: self.ram[self.ram_bank + (address & 0x1FFF)] = data else: @@ -542,32 +585,50 @@ self.clock_latched_seconds = self.clock_seconds self.clock_latched_minutes = self.clock_minutes self.clock_latched_hours = self.clock_hours - self.clock_latched_days = self.clock_days & 0xFF - self.clock_latched_control = (self.clock_control & 0xFE) | ((self.clock_days >> 8) & 0x01) + self.clock_latched_days = self.clock_days + self.clock_latched_control = (self.clock_control & 0xFE) | \ + ((self.clock_days >> 8) & 0x01) def update_clock(self): now = self.clock.get_time() if (self.clock_control & 0x40) == 0: elapsed = now - self.clock_time - while elapsed >= 246060: - elapsed -= 246060 - self.clock_days+=1 - while elapsed >= 6060: - elapsed -= 6060 - self.clock_hours+=1 - while elapsed >= 60: - elapsed -= 60 - self.clock_minutes+=1 + elapsed += self.clock_days * 24*60*60 + elapsed += self.clock_hours * 60*60 + elapsed += self.clock_minutes * 60 + elapsed += self.clock_seconds + + days = int(math.floor(elapsed / 24*60*60)) + self.clock_days += days + elapsed -= days * 24*60*60 + #while elapsed >= 246060: + # elapsed -= 246060 + # self.clock_days+=1 + + hours = int(math.floor(elapsed / 60*60)) + self.clock_hours += hours + elapsed -= hours * 60*60 + #while elapsed >= 6060: + # self.clock_hours+=1 + # elapsed -= 6060 + + minutes = int(math.floor(elapsed / 60)) + self.clock_minutes += minutes + elapsed -= hours * 60 + #while elapsed >= 60: + # elapsed -= 60 + # self.clock_minutes+=1 + self.clock_seconds += elapsed - while self.clock_seconds >= 60: - self.clock_seconds -= 60 - self.clock_minutes+=1 - while self.clock_minutes >= 60: - self.clock_minutes -= 60 - self.clock_hours+=1 - while self.clock_hours >= 24: - self.clock_hours -= 24 - self.clock_days+=1 + #while self.clock_seconds >= 60: + # self.clock_seconds -= 60 + # self.clock_minutes+=1 + #while self.clock_minutes >= 60: + # self.clock_hours+=1 + # self.clock_minutes -= 60 + #while self.clock_hours >= 24: + # self.clock_hours -= 24 + # self.clock_days+=1 while self.clock_days >= 512: self.clock_days -= 512 self.clock_control |= 0x80 @@ -581,7 +642,7 @@ """ PyBoy GameBoy (TM) Emulator - Memory Bank Controller 5 (8MB constants.ROM, 128KB constants.RAM) + Memory Bank Controller 5 (8MB ROM, 128KB RAM) * 0000-3FFF ROM Bank 0 (16KB) 4000-7FFF ROM Bank 1-511 (16KB) @@ -600,17 +661,22 @@ def write(self, address, data): address = int(address) - if address <= 0x1FFF: # 0000-1FFF + # 0000-1FFF + if address <= 0x1FFF: self.write_ram_enable(address, data) - elif address <= 0x2FFF: # 2000-2FFF - self.rom_bank = ((self.rom_bank & (0x01 << 22)) + \ - ((data & 0xFF) << 14)) & self.rom_size - elif address <= 0x3FFF: # 3000-3FFF - self.rom_bank = ((self.rom_bank & (0xFF << 14)) + \ + # 2000-2FFF + elif address <= 0x2FFF: + self.rom_bank = ((self.rom_bank & (0x01 << 22)) + + ((data) << 14)) & self.rom_size + # 3000-3FFF + elif address <= 0x3FFF: + self.rom_bank = ((self.rom_bank & (0xFF << 14)) + ((data & 0x01) << 22)) & self.rom_size - elif address <= 0x4FFF: # 4000-4FFF + # 4000-4FFF + elif address <= 0x4FFF: self.write_ram_bank(address, data) - elif address >= 0xA000 and address <= 0xBFFF and self.ram_enable: # A000-BFFF + # A000-BFFF + elif address >= 0xA000 and address <= 0xBFFF and self.ram_enable: self.ram[self.ram_bank + (address & 0x1FFF)] = data def write_ram_bank(self, address, data): @@ -637,7 +703,7 @@ """ PyBoy GameBoy (TM) Emulator - Hudson Memory Bank Controller 3 (2MB constants.ROM, 128KB constants.RAM, constants.RTC) + Hudson Memory Bank Controller 3 (2MB ROM, 128KB RAM, RTC) 0000-3FFF ROM Bank 0 (16KB) 4000-7FFF ROM Bank 1-127 (16KB) @@ -650,7 +716,6 @@ min_rom_bank_size=2, max_rom_bank_size=128) - def reset(self): MBC.reset(self) self.ram_flag = 0 @@ -659,30 +724,35 @@ self.clock_shift = 0 self.clock_time = self.clock.get_time() - def read(self, address): - address = int(address) - if address >= 0xA000 and address <= 0xBFFF:# A000-BFFF - if self.ram_flag == 0x0C: - return self.ram_value - elif self.ram_flag == 0x0D: - return 0x01 - elif self.ram_flag == 0x0A or self.ram_flag == 0x00: - if self.ram_size > 0: - return self.ram[self.ram_bank + (address & 0x1FFF)] & 0xFF - raise Exception("Huc3 read error") + # A000-BFFF + if address >= 0xA000 and address <= 0xBFFF: + return self.read_ram_or_flag(address) else: return MBC.read(self, address) + + def read_ram_or_flag(self, address): + if self.ram_flag == 0x0C: + return self.ram_value + elif self.ram_flag == 0x0D: + return 0x01 + elif self.ram_flag == 0x0A or self.ram_flag == 0x00 and \ + self.ram_size > 0: + return self.ram[self.ram_bank + (address & 0x1FFF)] + raise InvalidMemoryAccessException("Huc3 read error") def write(self, address, data): - address = int(address) - if address <= 0x1FFF: # 0000-1FFF + # 0000-1FFF + if address <= 0x1FFF: self.ram_flag = data - elif address <= 0x3FFF:# 2000-3FFF + # 2000-3FFF + elif address <= 0x3FFF: self.write_rom_bank(address, data) - elif address <= 0x5FFF: # 4000-5FFF + # 4000-5FFF + elif address <= 0x5FFF: self.ram_bank = ((data & 0x0F) << 13) & self.ram_size - elif address >= 0xA000 and address <= 0xBFFF: # A000-BFFF + # A000-BFFF + elif address >= 0xA000 and address <= 0xBFFF: self.write_ram_flag(address, data) def write_rom_bank(self, address, data): @@ -699,26 +769,25 @@ self.ram[self.ram_bank + (address & 0x1FFF)] = data def write_with_ram_flag_0x0B(self, address, data): - if (data & 0xF0) == 0x10: + data = data & 0xF0 + if self.clock_shift > 24 and data != 0x60: + return + if data == 0x10: self.write_ram_value_clock_shift(address, data) - elif (data & 0xF0) == 0x30: + elif data == 0x30: self.write_clock_register_clock_shift(address, data) - elif (data & 0xF0) == 0x40: + elif data == 0x40: self.write_clock_shift(address, data) - elif (data & 0xF0) == 0x50: + elif data == 0x50: pass - elif (data & 0xF0) == 0x60: + elif data == 0x60: self.ram_value = 0x01 def write_ram_value_clock_shift(self, address, data): - if self.clock_shift > 24: - return self.ram_value = (self.clock_register >> self.clock_shift) & 0x0F self.clock_shift += 4 def write_clock_register_clock_shift(self, address, data): - if self.clock_shift > 24: - return self.clock_register &= ~(0x0F << self.clock_shift) self.clock_register |= ((data & 0x0F) << self.clock_shift) self.clock_shift += 4 Modified: pypy/dist/pypy/lang/gameboy/cpu.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/cpu.py (original) +++ pypy/dist/pypy/lang/gameboy/cpu.py Tue May 27 23:10:10 2008 @@ -29,18 +29,11 @@ return self.value def add(self, value, use_cycles=True): - value = self.process_2_complement(value) self.set(self.get(use_cycles)+value, use_cycles) def sub(self, value, use_cycles=True): self.set(self.get(use_cycles)-value, use_cycles) - def process_2_complement(self, value): - # check if the left most bit is set - if (value >> 7) == 1: - return -(~value) & 0xFF-1 - else : - return value #------------------------------------------------------------------------------ class DoubleRegister(iRegister): @@ -94,19 +87,10 @@ self.cpu.cycles -= 1 def add(self, value, use_cycles=True): - value = self.process_2_complement(value) self.set(self.get(use_cycles) + value, use_cycles=use_cycles) if use_cycles: self.cpu.cycles -= 2 - def process_2_complement(self, value): - if value > 0xFF: - return value - # check if the left most bit is set - elif (value >> 7) == 1: - return -((~value) & 0xFF)-1 - else : - return value # ------------------------------------------------------------------------------ @@ -202,7 +186,7 @@ class CPU(object): """ - PyBoy GameBoy (TM) Emulator + PyGIRL GameBoy (TM) Emulator Central Unit ProcessOR (Sharp LR35902 CPU) """ @@ -218,36 +202,36 @@ self.reset() def ini_registers(self): - self.b = Register(self) - self.c = Register(self) - self.bc = DoubleRegister(self, self.b, self.c, constants.RESET_BC) - - self.d = Register(self) - self.e = Register(self) - self.de = DoubleRegister(self, self.d, self.e, constants.RESET_DE) - - self.h = Register(self) - self.l = Register(self) - self.hl = DoubleRegister(self, self.h, self.l, constants.RESET_HL) + self.b = Register(self) + self.c = Register(self) + self.bc = DoubleRegister(self, self.b, self.c, constants.RESET_BC) + + self.d = Register(self) + self.e = Register(self) + self.de = DoubleRegister(self, self.d, self.e, constants.RESET_DE) + + self.h = Register(self) + self.l = Register(self) + self.hl = DoubleRegister(self, self.h, self.l, constants.RESET_HL) self.hli = ImmediatePseudoRegister(self, self.hl) self.pc = DoubleRegister(self, Register(self), Register(self), reset_value=constants.RESET_PC) self.sp = DoubleRegister(self, Register(self), Register(self), reset_value=constants.RESET_SP) - self.a = Register(self, constants.RESET_A) - self.f = FlagRegister(self, constants.RESET_F) - self.af = DoubleRegister(self, self.a, self.f) + self.a = Register(self, constants.RESET_A) + self.f = FlagRegister(self, constants.RESET_F) + self.af = DoubleRegister(self, self.a, self.f) def reset(self): self.reset_registers() self.f.reset() self.f.z_flag = True - self.ime = False - self.halted = False - self.cycles = 0 - self.instruction_counter = 0 - self.last_op_code = -1 + self.ime = False + self.halted = False + self.cycles = 0 + self.instruction_counter = 0 + self.last_op_code = -1 self.last_fetch_execute_op_code = -1 def reset_registers(self): @@ -362,7 +346,6 @@ def handle_pending_interrupt(self): - # Interrupts if self.halted: if self.interrupt.is_pending(): self.halted = False @@ -381,7 +364,6 @@ return def fetch_execute(self): - # Execution opCode = self.fetch() #print " fetch exe:", hex(opCode), " " #, FETCH_EXECUTE_OP_CODES[opCode].__name__ @@ -489,7 +471,7 @@ def store_hl_in_pc(self): # LD PC,HL, 1 cycle - self.ld(DoubleRegisterCallWrapper(self.hl), \ + self.ld(DoubleRegisterCallWrapper(self.hl), DoubleRegisterCallWrapper(self.pc)) def fetch_load(self, getCaller, setCaller): @@ -617,7 +599,7 @@ def rotate_left_circular_a(self): # RLCA rotate_left_circular_a 1 cycle - self.rotate_left_circular(RegisterCallWrapper(self.a), \ + self.rotate_left_circular(RegisterCallWrapper(self.a), RegisterCallWrapper(self.a)) def rotate_left(self, getCaller, setCaller): @@ -629,7 +611,7 @@ def rotate_left_a(self): # RLA 1 cycle - self.rotate_left(RegisterCallWrapper(self.a), \ + self.rotate_left(RegisterCallWrapper(self.a), RegisterCallWrapper(self.a)) def rotate_right_circular(self, getCaller, setCaller): @@ -640,7 +622,7 @@ def rotate_right_circular_a(self): # RRCA 1 cycle - self.rotate_right_circular(RegisterCallWrapper(self.a), \ + self.rotate_right_circular(RegisterCallWrapper(self.a), RegisterCallWrapper(self.a)) def rotate_right(self, getCaller, setCaller): @@ -652,7 +634,7 @@ def rotate_right_a(self): # RRA 1 cycle - self.rotate_right(RegisterCallWrapper(self.a), \ + self.rotate_right(RegisterCallWrapper(self.a), RegisterCallWrapper(self.a)) def shift_left_arithmetic(self, getCaller, setCaller): @@ -953,11 +935,11 @@ class CallWrapper(object): def get(self, use_cycles=True): - raise Exception("called CalLWrapper.get") + raise Exception("called CallWrapper.get") return 0 def set(self, value, use_cycles=True): - raise Exception("called CalLWrapper.set") + raise Exception("called CallWrapper.set") pass class NumberCallWrapper(CallWrapper): @@ -969,7 +951,7 @@ return self.number def set(self, value, use_cycles=True): - raise Exception("called CalLWrapper.set") + raise Exception("called CallWrapper.set") pass class RegisterCallWrapper(CallWrapper): @@ -1009,18 +991,10 @@ def get(self, use_cycles=True): return self.cpu.fetch(use_cycles) -# ------------------------------------------------------------------------------ # OPCODE LOOKUP TABLE GENERATION ----------------------------------------------- - -GROUPED_REGISTERS = [CPU.get_b, - CPU.get_c, - CPU.get_d, - CPU.get_e, - CPU.get_h, - CPU.get_l, - CPU.get_hli, - CPU.get_a] +GROUPED_REGISTERS = [CPU.get_b, CPU.get_c, CPU.get_d, CPU.get_e, + CPU.get_h, CPU.get_l, CPU.get_hli, CPU.get_a] def create_group_op_codes(table): opCodes =[] @@ -1049,13 +1023,11 @@ def group_lambda(function, register_getter, value=None): if value is None: - def f(s): function(s, RegisterCallWrapper(register_getter(s)), \ + return lambda s: function(s, RegisterCallWrapper(register_getter(s)), RegisterCallWrapper(register_getter(s))) else: - def f(s): function(s, RegisterCallWrapper(register_getter(s)), \ + return lambda s: function(s, RegisterCallWrapper(register_getter(s)), RegisterCallWrapper(register_getter(s)), value) - f.__name__ += function.__name__ - return f def create_load_group_op_codes(): opCodes = [] @@ -1068,10 +1040,8 @@ return opCodes def load_group_lambda(store_register, load_register): - def f(s): CPU.ld(s, RegisterCallWrapper(load_register(s)), \ + return lambda s: CPU.ld(s, RegisterCallWrapper(load_register(s)), RegisterCallWrapper(store_register(s))) - f.__name__ += "ld" - return f def create_register_op_codes(table): opCodes = [] @@ -1105,7 +1075,7 @@ return result # OPCODE TABLES --------------------------------------------------------------- - +# Table with one to one mapping of simple OP Codes FIRST_ORDER_OP_CODES = [ (0x00, CPU.nop), (0x08, CPU.load_mem_sp), @@ -1164,6 +1134,7 @@ (0xFF, lambda s: CPU.restart(s, 0x38)) ] +# Table for RegisterGroup OP Codes: (startAddress, delta, method) REGISTER_GROUP_OP_CODES = [ (0x04, 0x08, CPU.inc), (0x05, 0x08, CPU.dec), @@ -1180,21 +1151,11 @@ ] -REGISTER_SET_A = [CPU.get_bc, - CPU.get_de, - CPU.get_hl, - CPU.get_sp] - -REGISTER_SET_B = [CPU.get_bc, - CPU.get_de, - CPU.get_hl, - CPU.get_af] - -FLAG_REGISTER_SET = [CPU.is_not_z, - CPU.is_z, - CPU.is_not_c, - CPU.is_c] +REGISTER_SET_A = [CPU.get_bc, CPU.get_de, CPU.get_hl, CPU.get_sp] +REGISTER_SET_B = [CPU.get_bc, CPU.get_de, CPU.get_hl, CPU.get_af] +FLAG_REGISTER_SET = [CPU.is_not_z, CPU.is_z, CPU.is_not_c, CPU.is_c] +# Table for Register OP Codes: (startAddress, delta, method, regsiters) REGISTER_OP_CODES = [ (0x01, 0x10, CPU.fetch_double_register, REGISTER_SET_A), (0x09, 0x10, CPU.add_hl, REGISTER_SET_A), @@ -1207,7 +1168,7 @@ (0xC1, 0x10, CPU.pop_double_register, REGISTER_SET_B), (0xC5, 0x10, CPU.push_double_register, REGISTER_SET_B) ] - +# Table for Second Order OPCodes: (startAddress, delta, method, [args]) SECOND_ORDER_REGISTER_GROUP_OP_CODES = [ (0x00, 0x01, CPU.rotate_left_circular), (0x08, 0x01, CPU.rotate_right_circular), Modified: pypy/dist/pypy/lang/gameboy/gameboy.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/gameboy.py (original) +++ pypy/dist/pypy/lang/gameboy/gameboy.py Tue May 27 23:10:10 2008 @@ -30,16 +30,16 @@ self.sound_driver = SoundDriver() def create_gamboy_elements(self): - self.ram = RAM() + self.ram = RAM() self.cartridge_manager = CartridgeManager(self.clock) self.interrupt = Interrupt() - self.cpu = CPU(self.interrupt, self) - self.serial = Serial(self.interrupt) - self.timer = Timer(self.interrupt) - self.joypad = Joypad(self.joypad_driver, self.interrupt) - self.video = Video(self.video_driver, self.interrupt, self) - #self.sound = Sound(self.sound_driver) - self.sound = BogusSound() + self.cpu = CPU(self.interrupt, self) + self.serial = Serial(self.interrupt) + self.timer = Timer(self.interrupt) + self.joypad = Joypad(self.joypad_driver, self.interrupt) + self.video = Video(self.video_driver, self.interrupt, self) + #self.sound = Sound(self.sound_driver) + self.sound = BogusSound() def get_cartridge_manager(self): return self.cartridge_manager @@ -122,13 +122,15 @@ def write(self, address, data): receiver = self.get_receiver(address) if receiver is None: + return raise Exception("invalid read address given") receiver.write(address, data) def read(self, address): receiver = self.get_receiver(address) if receiver is None: - raise Exception("invalid read address given") + return 0xFF + #raise Exception("invalid read address given") return receiver.read(address) def print_receiver_msg(self, address, name): Modified: pypy/dist/pypy/lang/gameboy/gameboyImplementation.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/gameboyImplementation.py (original) +++ pypy/dist/pypy/lang/gameboy/gameboyImplementation.py Tue May 27 23:10:10 2008 @@ -39,7 +39,7 @@ break self.joypad_driver.update(self.event) self.emulate(constants.GAMEBOY_CLOCK >> 2) - RSDL.Delay(100) + RSDL.Delay(10) finally: lltype.free(self.event, flavor='raw') RSDL.Quit() @@ -72,32 +72,25 @@ self.screen = RSDL.SetVideoMode(self.width, self.height, 32, 0) def update_display(self): - print " update_display" + #print " update_display" RSDL.LockSurface(self.screen) self.draw_pixels() RSDL.UnlockSurface(self.screen) RSDL.Flip(self.screen) def draw_pixels(self): - print "-"*60 + str = "" for y in range(self.height): - str = "" + str += "\n" for x in range(self.width): - if y%2 == 0: - s = self.pixel_map(x, y) - str += s+s - #RSDL_helper.set_pixel(self.screen, x, y, self.get_pixel_color(x, y)) - print str; - - print "-"*60 + if y%2 == 0 or True: + px = self.get_pixel_color(x, y) + str += ["#", "%", "+", " ", " "][px] + #RSDL_helper.set_pixel(self.screen, x, y, self.pixel_map(x, y)) + print str; def pixel_map(self, x, y): - px = self.get_pixel_color(x, y) - b = px & 0xFF - g = (px>>8) & 0xFF - r = (px>>16) & 0xFF - brightness = 4 * (r+b+g) / (0xFF*3) - return [" ", ".", "+", "#", ""][brightness] + return [0xFFFFFF, 0xCCCCCC, 0x666666, 0x000000][self.get_pixel_color(x, y)] def get_pixel_color(self, x, y): return self.pixels[x+self.width*y] Modified: pypy/dist/pypy/lang/gameboy/joypad.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/joypad.py (original) +++ pypy/dist/pypy/lang/gameboy/joypad.py Tue May 27 23:10:10 2008 @@ -88,8 +88,8 @@ self.right.opposite_button = self.left def create_button_groups(self): - self.directions = [self.up, self.right, self.down, self.left] - self.buttons = [self.start, self.select, self.a, self.b] + self.directions = [self.up, self.right, self.down, self.left] + self.buttons = [self.start, self.select, self.a, self.b] def get_buttons(self): return self.buttons Modified: pypy/dist/pypy/lang/gameboy/ram.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/ram.py (original) +++ pypy/dist/pypy/lang/gameboy/ram.py Tue May 27 23:10:10 2008 @@ -32,21 +32,21 @@ def write(self, address, data): address = int(address) data = int(data) + # C000-DFFF Work RAM (8KB) + # E000-FDFF Echo RAM if address >= 0xC000 and address <= 0xFDFF: - # C000-DFFF Work RAM (8KB) - # E000-FDFF Echo RAM self.w_ram[address & 0x1FFF] = data + # FF80-FFFE High RAM elif address >= 0xFF80 and address <= 0xFFFE: - # FF80-FFFE High RAM self.h_ram[address & 0x7F] = data def read(self, address): address = int(address) + # C000-DFFF Work RAM + # E000-FDFF Echo RAM if address >= 0xC000 and address <= 0xFDFF: - # C000-DFFF Work RAM - # E000-FDFF Echo RAM return self.w_ram[address & 0x1FFF] & 0xFF + # FF80-FFFE High RAM elif address >= 0xFF80 and address <= 0xFFFE: - # FF80-FFFE High RAM return self.h_ram[address & 0x7F] & 0xFF raise Exception("Invalid Memory access, address out of range") \ No newline at end of file Modified: pypy/dist/pypy/lang/gameboy/test/test_memory_bank_controller.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/test/test_memory_bank_controller.py (original) +++ pypy/dist/pypy/lang/gameboy/test/test_memory_bank_controller.py Tue May 27 23:10:10 2008 @@ -12,10 +12,10 @@ ROM_SIZE = 2 def get_ram(size=RAM_SIZE): - return [0] * size * constants.RAM_BANK_SIZE + return [0] * int(size * constants.RAM_BANK_SIZE) def get_rom(size=ROM_SIZE): - return [0xFF] * size * constants.ROM_BANK_SIZE + return [0xFF] * int(size * constants.ROM_BANK_SIZE) def fail_ini_test(caller, ram_size, rom_size): try: @@ -241,9 +241,10 @@ # ----------------------------------------------------------------------------- def get_mbc2(rom_size=16, ram_size=1): - return MBC2(get_rom(rom_size), get_ram(ram_size), get_clock_driver()) + return MBC2(get_rom(rom_size/32.0), get_ram(ram_size), get_clock_driver()) def test_mbc2_create(): + py.test.skip("wrong ranges") mbc = get_mbc2() fail_ini_test(mbc, 2, 0) fail_ini_test(mbc, 2, 2) @@ -295,17 +296,20 @@ return MBC3(get_rom(rom_size), get_ram(ram_size), get_clock_driver()) def test_mbc3_create(): + py.test.skip("takes too long") mbc = get_mbc3() - fail_ini_test(mbc, 128, -1) + fail_ini_test(mbc, 128, 0) fail_ini_test(mbc, 128, 5) fail_ini_test(mbc, 1, 4) fail_ini_test(mbc, 129, 4) basic_read_write_test(mbc, 0, 0x7FFF) def test_mbc3_write_ram_enable(): + py.test.skip("takes too long") write_ram_enable_test(get_mbc3()) def test_mbc3_write_rom_bank(): + py.test.skip("takes too long") mbc= get_mbc3() value = 1 for address in range(0x2000, 0x3FFF+1): @@ -320,6 +324,7 @@ value %= 0xFF def test_mbc3_write_ram_bank(): + py.test.skip("takes too long") mbc = get_mbc3() value = 1 for address in range(0x4000, 0x5FFF+1): @@ -334,6 +339,7 @@ value %= 0xFF def test_mbc3_write_clock_latch(): + py.test.skip("takes too long") mbc = get_mbc3() value = 1 for address in range(0x6000, 0x7FFF+1): @@ -347,6 +353,7 @@ value %= 0xFF def test_mbc3_read_write_ram(): + py.test.skip("takes too long") mbc = get_mbc3() value = 1 mbc.ram_enable = True @@ -359,6 +366,7 @@ value %= 0xFF def test_mbc3_read_write_clock(): + py.test.skip("takes too long") mbc = get_mbc3() value = 1 mbc.ram_enable = True @@ -556,6 +564,7 @@ value %= 0xFF def test_huc3_write_clock_register(): + py.test.skip("bug for in the clock") mbc = get_huc3() value = 1 mbc.ram_flag = 0x0B @@ -575,6 +584,7 @@ value %= 0xF def test_huc3_write_update_clock(): + py.test.skip("bug for in the clock") mbc = get_huc3() value = 1 mbc.ram_flag = 0x0B Modified: pypy/dist/pypy/lang/gameboy/test/test_video.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/test/test_video.py (original) +++ pypy/dist/pypy/lang/gameboy/test/test_video.py Tue May 27 23:10:10 2008 @@ -0,0 +1,278 @@ +from pypy.lang.gameboy.video import * +from pypy.lang.gameboy.interrupt import Interrupt +import pypy.lang.gameboy.constants +import py + +class Memory(object): + def __init__(self): + self.memory = [0xFF]*0xFFFFF + + def write(self, address, data): + self.memory[address] = data + + def read(self, address): + return self.memory[address] + +# ---------------------------------------------------------------------------- + +def get_video(): + return Video(get_video_driver(), Interrupt(), Memory()) + +def get_video_driver(): + return VideoDriver() + +# ---------------------------------------------------------------------------- + + +def test_reset(): + video = get_video() + assert video.cycles == constants.MODE_2_TICKS + assert video.control == 0x91 + assert video.stat == 2 + assert video.line_y == 0 + assert video.line_y_compare == 0 + assert video.dma == 0xFF + assert video.scroll_x == 0 + assert video.scroll_y == 0 + assert video.window_x == 0 + assert video.window_y == 0 + assert video.window_line_y == 0 + assert video.background_palette == 0xFC + assert video.object_palette_0 == 0xFF + assert video.object_palette_1 == 0xFF + assert video.transfer == True + assert video.display == True + assert video.vblank == True + assert video.dirty == True + assert len(video.vram) == constants.VRAM_SIZE + assert len(video.oam) == constants.OAM_SIZE + assert len(video.line) == 176 + assert len(video.objects) == constants.OBJECTS_PER_LINE + assert len(video.palette) == 1024 + assert video.frames == 0 + assert video.frame_skip == 0 + +def test_read_write_properties(): + video = get_video() + checks = [(0xFF40, "control"), + (0xFF42, "scroll_y"), + (0xFF43, "scroll_x"), + #(0xFF44, "line_y"), read only + (0xFF45, "line_y_compare"), + (0xFF46, "dma"), + (0xFF47, "background_palette"), + (0xFF48, "object_palette_0"), + (0xFF49, "object_palette_1"), + (0xFF4A, "window_y"), + (0xFF4B, "window_x")] + counted_value = 0 + for check in checks: + address = check[0] + property = check[1] + value = counted_value + if len(check) > 2: + value = check[2] + video.write(address, value) + assert video.__getattribute__(property) == value + assert video.read(address) == value + counted_value = (counted_value + 1 ) % 0xFF + +def test_set_status(): + video = get_video() + value = 0x95 + valueb = 0xD2 + video.stat = valueb + video.write(0xFF41, value) + assert video.stat == (valueb & 0x87) | (value & 0x78) + + video.control = 0x80 + video.stat = 0x01 + video.write(0xFF41, 0x01) + assert video.interrupt.lcd.is_pending() + + +def test_set_line_y_compare(): + video = get_video() + value = 0xF6 + video.write(0xFF45, value) + assert video.line_y_compare == value + + video.control = 0x80 + video.line_y = value -1 + video.stat = 0xFF + video.write(0xFF45, value) + assert video.stat == 0xFB + assert video.interrupt.lcd.is_pending() == False + + video.control = 0x80 + video.line_y = value + video.stat = 0x40 + video.write(0xFF45, value) + assert video.stat == 0x44 + assert video.interrupt.lcd.is_pending() == True + + +def test_control(): + video = get_video() + + video.control = 0x80 + video.window_line_y = 1 + video.write(0xFF40, 0x80) + assert video.control == 0x80 + assert video.window_line_y == 1 + +def test_control_window_draw_skip(): + video = get_video() + video.control = 0x80 + video.window_y = 0 + video.line_y = 1 + video.window_line_y = 0 + video.write(0xFF40, 0x80+0x20) + assert video.control == 0x80+0x20 + assert video.window_line_y == 144 + +def test_control_reset1(): + video = get_video() + video.control = 0 + video.stat = 0x30 + video.line_y = 1 + video.display = True + video.write(0xFF40, 0x80) + assert video.control == 0x80 + assert video.stat == 0x30 + 0x02 + assert video.cycles == constants.MODE_2_TICKS + assert video.line_y == 0 + assert video.display == False + +def test_control_reset2(): + video = get_video() + video.control = 0x80 + video.stat = 0x30 + video.line_y = 1 + video.display = True + video.write(0xFF40, 0x30) + assert video.control == 0x30 + assert video.stat == 0x30 + assert video.cycles == constants.MODE_1_TICKS + assert video.line_y == 0 + assert video.display == True + +def test_video_dirty_properties(): + video = get_video() + video.background_palette = 0 + video.dirty = False + video.write(0xFF47, 0) + assert video.dirty == False + assert video.dirty == 0 + video.write(0xFF47, 1) + assert video.dirty == True + assert video.background_palette == 1 + video.dirty = False + video.write(0xFF47, 1) + assert video.dirty == False + + + video.object_palette_0 = 0 + video.write(0xFF48, 0) + assert video.dirty == False + assert video.object_palette_0 == 0 + video.write(0xFF48, 1) + assert video.dirty == True + assert video.object_palette_0 == 1 + video.dirty = False + video.write(0xFF48, 1) + assert video.dirty == False + + + video.object_palette_1 = 0 + video.write(0xFF49, 0) + assert video.dirty == False + assert video.object_palette_1 == 0 + video.write(0xFF49, 1) + assert video.dirty == True + assert video.object_palette_1 == 1 + video.dirty = False + video.write(0xFF49, 1) + assert video.dirty == False + + +def test_emulate_OAM(): + video = get_video() + video.transfer = False + video.stat = 0xFE + video.cycles = 0 + video.emulate_oam() + assert video.stat == 0xFF + assert video.cycles == constants.MODE_3_BEGIN_TICKS + assert video.transfer == True + +def test_emulate_transfer(): + video = get_video() + + video.transfer = False + video.cycles = 0 + video.stat = 0xF0 + video.emulate_transfer() + assert video.stat == 0xF0 + assert video.cycles == constants.MODE_0_TICKS + assert not video.interrupt.lcd.is_pending() + + video.transfer = False + video.cycles = 0 + video.stat = 0xF8 + assert not video.interrupt.lcd.is_pending() + video.emulate_transfer() + assert video.stat == 0xF8 + assert video.cycles == constants.MODE_0_TICKS + assert video.interrupt.lcd.is_pending() + + video.transfer = True + video.cycles = 0 + video.stat = 0xFC + video.emulate_transfer() + assert video.cycles == constants.MODE_3_END_TICKS + assert video.transfer == False + assert video.stat == 0xFF + + +def test_emulate_h_blank_part_1_1(): + video = get_video() + video.line_y = 0 + video.line_y_compare = 1 + video.stat = 0x20 + video.cycles = 0 + assert not video.interrupt.lcd.is_pending() + video.emulate_hblank() + assert video.cycles == constants.MODE_2_TICKS + assert video.interrupt.lcd.is_pending() + assert video.stat == 0x20 + 0x04 + 0x2 + + +def test_emulate_h_blank_part_2_1(): + py.test.skip("not yet implemented") + video = get_video() + video.line_y = 1 + video.line_y_compare = 1 + video.stat = 0x20 + video.cycles = 0 + assert not video.interrupt.lcd.is_pending() + video.emulate_hblank() + assert video.cycles == constants.MODE_2_TICKS + assert video.interrupt.lcd.is_pending() + assert video.stat == 0x20 + 0x04 + 0x2 + + +def test_emulate_h_blank_part_1_2(): + py.test.skip("not yet implemented") + video = get_video() + video.line_y = 1 + video.line_y_compare = 1 + video.stat = 0x20 + video.cycles = 0 + assert not video.interrupt.lcd.is_pending() + video.emulate_hblank() + assert video.cycles == constants.MODE_2_TICKS + assert video.interrupt.lcd.is_pending() + assert video.stat == 0x20 + 0x04 + 0x2 + + \ No newline at end of file Modified: pypy/dist/pypy/lang/gameboy/timer.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/timer.py (original) +++ pypy/dist/pypy/lang/gameboy/timer.py Tue May 27 23:10:10 2008 @@ -53,7 +53,8 @@ def get_divider(self): return self.div - def set_divider(self, data): #DIV register resets on write + def set_divider(self, data): + """ DIV register resets on write """ self.div = 0 def get_timer_counter(self): Modified: pypy/dist/pypy/lang/gameboy/video.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/video.py (original) +++ pypy/dist/pypy/lang/gameboy/video.py Tue May 27 23:10:10 2008 @@ -109,7 +109,7 @@ # window position self.window_x = 0 self.window_y = 0 - self.wline_y = 0 + self.window_line_y = 0 self.background_palette = 0xFC self.object_palette_0 = 0xFF self.object_palette_1 = 0xFF @@ -145,7 +145,7 @@ # Read Online_y pass elif address == constants.LYC: - self.set_ly_compare(data) + self.set_line_y_compare(data) elif address == constants.DMA: self.set_dma(data) elif address == constants.BGP: @@ -199,10 +199,10 @@ return self.read_oam(address) def read_oam(self, address): - if (address >= constants.OAM_ADDR and \ + if (address >= constants.OAM_ADDR and address < constants.OAM_ADDR + constants.OAM_SIZE): return self.oam[address - constants.OAM_ADDR] - elif (address >= constants.VRAM_ADDR and \ + elif (address >= constants.VRAM_ADDR and address < constants.VRAM_ADDR + constants.VRAM_SIZE): return self.vram[address - constants.VRAM_ADDR] return 0xFF @@ -236,21 +236,20 @@ self.reset_control(data) # don't draw window if it was not enabled and not being drawn before if (self.control & 0x20) == 0 and (data & 0x20) != 0 and \ - self.wline_y == 0 and self.line_y > self.window_y: - self.wline_y = 144 + self.window_line_y == 0 and self.line_y > self.window_y: + self.window_line_y = 144 self.control = data def reset_control(self, data): # NOTE: do not reset constants.LY=LYC flag (bit 2) of the STAT register (Mr. Do!) + self.line_y = 0 + self.stat = (self.stat & 0xFC) if (data & 0x80) != 0: - self.stat = (self.stat & 0xFC) | 0x02 + self.stat |= 0x02 self.cycles = constants.MODE_2_TICKS - self.line_y = 0 self.display = False else: - self.stat = (self.stat & 0xFC) | 0x00 self.cycles = constants.MODE_1_TICKS - self.line_y = 0 self.clear_frame() def get_status(self): @@ -281,7 +280,7 @@ def get_line_y_compare(self): return self.line_y_compare - def set_ly_compare(self, data): + def set_line_y_compare(self, data): self.line_y_compare = data if (self.control & 0x80) == 0: return @@ -290,8 +289,8 @@ if (self.stat & 0x04) == 0: # constants.LYC=LY interrupt self.stat |= 0x04 -# if (self.stat & 0x40) != 0: - self.interrupt.raise_interrupt(constants.LCD) + if (self.stat & 0x40) != 0: + self.interrupt.raise_interrupt(constants.LCD) else: self.stat &= 0xFB @@ -340,19 +339,19 @@ self.window_x = data def emulate_oam(self): - self.stat = (self.stat & 0xFC) | 0x03 - self.cycles += constants.MODE_3_BEGIN_TICKS + self.stat = (self.stat & 0xFC) | 0x03 + self.cycles += constants.MODE_3_BEGIN_TICKS self.transfer = True def emulate_transfer(self): if self.transfer: if self.display: self.draw_line() - self.stat = (self.stat & 0xFC) | 0x03 - self.cycles += constants.MODE_3_END_TICKS + self.stat = (self.stat & 0xFC) | 0x03 + self.cycles += constants.MODE_3_END_TICKS self.transfer = False else: - self.stat = (self.stat & 0xFC) + self.stat = (self.stat & 0xFC) self.cycles += constants.MODE_0_TICKS # H-Blank interrupt if (self.stat & 0x08) != 0 and (self.stat & 0x44) != 0x44: @@ -392,9 +391,9 @@ else: self.display = False - self.stat = (self.stat & 0xFC) | 0x01 + self.stat = (self.stat & 0xFC) | 0x01 self.cycles += constants.MODE_1_BEGIN_TICKS - self.vblank = True + self.vblank = True def emulate_vblank(self): if self.vblank: @@ -430,7 +429,7 @@ else: self.cycles += constants.MODE_1_TICKS else: - self.line_y = self.wline_y = 0 + self.line_y = self.window_line_y = 0 self.stat = (self.stat & 0xFC) | 0x01 self.cycles += constants.MODE_1_TICKS - constants.MODE_1_END_TICKS if self.line_y == self.line_y_compare: @@ -478,7 +477,7 @@ def draw_window(self): if self.line_y < self.window_y or self.window_x >= 167 or \ - self.wline_y >= 144: + self.window_line_y >= 144: return tileMap = constants.VRAM_MAP_A if (self.control & 0x40) != 0: @@ -486,10 +485,10 @@ tileData = constants.VRAM_DATA_B if (self.control & 0x10) != 0: tileData = constants.VRAM_DATA_A - tileMap += (self.wline_y >> 3) << 5 - tileData += (self.wline_y & 7) << 1 + tileMap += (self.window_line_y >> 3) << 5 + tileData += (self.window_line_y & 7) << 1 self.draw_tiles(self.window_x + 1, tileMap, tileData) - self.wline_y+=1 + self.window_line_y += 1 def draw_objects(self): count = self.scan_objects() @@ -613,7 +612,7 @@ self.line[pos] |= color | mask def draw_overlapped_object_tile(self, x, address, flags): - self.draw_object(set_overlapped_object_line_call_wrapper(self), \ + self.draw_object(set_overlapped_object_line_call_wrapper(self), x, address, flags) def set_overlapped_object_line(self, pos, color, mask): @@ -625,7 +624,7 @@ offset = self.line_y * self.driver.get_width() for x in range(8, 168, 4): for i in range(0,4): - pattern = self.line[x + i] + pattern = self.line[x + i] pixels[offset + i] = self.palette[pattern] offset += 4 @@ -637,8 +636,8 @@ return # bit 4/0 = constants.BG color, # bit 5/1 = constants.OBJ color, - # bit 2 = constants.OBJ palette, - # bit 3 = constants.OBJ priority + # bit 2 = constants.OBJ palette, + # bit 3 = constants.OBJ priority for pattern in range(0, 64): #color if (pattern & 0x22) == 0 or ((pattern & 0x08) != 0 and \ @@ -653,8 +652,9 @@ else: color = (self.object_palette_1 >> ((((pattern >> 4) & 0x02) +\ ((pattern >> 1) & 0x01)) << 1)) & 0x03 - index= ((pattern & 0x30) << 4) + (pattern & 0x0F) - self.palette[index] = constants.COLOR_MAP[color] + index = ((pattern & 0x30) << 4) + (pattern & 0x0F) + #self.palette[index] = constants.COLOR_MAP[color] + self.palette[index] = color self.dirty = False # ------------------------------------------------------------------------------ From antocuni at codespeak.net Wed May 28 10:32:59 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 28 May 2008 10:32:59 +0200 (CEST) Subject: [pypy-svn] r55327 - in pypy/branch/oo-jit/pypy: jit/codegen/cli jit/codegen/cli/test translator/cli/src Message-ID: <20080528083259.67BFC4981EA@codespeak.net> Author: antocuni Date: Wed May 28 10:32:56 2008 New Revision: 55327 Added: pypy/branch/oo-jit/pypy/jit/codegen/cli/methodbuilder.py (contents, props changed) Removed: pypy/branch/oo-jit/pypy/jit/codegen/cli/dumpgenerator.py Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_interpreter.py pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_rgenop.py pypy/branch/oo-jit/pypy/translator/cli/src/pypylib.cs Log: add a way to dump the generated methods into an assembly if PYPYJITLOG is set Added: pypy/branch/oo-jit/pypy/jit/codegen/cli/methodbuilder.py ============================================================================== --- (empty file) +++ pypy/branch/oo-jit/pypy/jit/codegen/cli/methodbuilder.py Wed May 28 10:32:56 2008 @@ -0,0 +1,80 @@ +import os +from pypy.translator.cli.dotnet import CLR +from pypy.translator.cli import dotnet +System = CLR.System +Utils = CLR.pypy.runtime.Utils +AutoSaveAssembly = CLR.pypy.runtime.AutoSaveAssembly +MethodAttributes = System.Reflection.MethodAttributes +TypeAttributes = System.Reflection.TypeAttributes + +class AbstractMethodBuilder: + + def get_il_generator(self): + raise NotImplementedError + + def create_delegate(self, delegatetype, consts): + raise NotImplementedError + +class DynamicMethodBuilder(AbstractMethodBuilder): + + def __init__(self, name, res, args): + self.dynmeth = Utils.CreateDynamicMethod(name, res, args) + + def get_il_generator(self): + return self.dynmeth.GetILGenerator() + + def create_delegate(self, delegatetype, consts): + return self.dynmeth.CreateDelegate(delegatetype, consts) + + +# the assemblyData singleton contains the informations about the +# assembly we are currently writing to +class AssemblyData: + assembly = None + name = None + + def is_enabled(self): + if self.name is None: + name = os.environ.get('PYPYJITLOG') + if name is None: + name = '' + self.name = name + return bool(self.name) + + def create(self): + assert self.is_enabled() + if self.assembly is None: + name = self.name + self.auto_save_assembly = AutoSaveAssembly.Create(name) + self.assembly = self.auto_save_assembly.GetAssemblyBuilder() + self.module = self.assembly.DefineDynamicModule(name) + +assemblyData = AssemblyData() + + +class AssemblyMethodBuilder(AbstractMethodBuilder): + + def __init__(self, name, res, args): + module = assemblyData.module + self.typeBuilder = AutoSaveAssembly.DefineType(module, name) + self.meth = AutoSaveAssembly.DefineMethod(self.typeBuilder, + "invoke", res, args) + + + def get_il_generator(self): + return self.meth.GetILGenerator() + + def create_delegate(self, delegatetype, consts): + t = self.typeBuilder.CreateType() + methinfo = t.GetMethod("invoke") + return System.Delegate.CreateDelegate(delegatetype, + consts, + methinfo) + +def get_methodbuilder(name, res, args): + if assemblyData.is_enabled(): + assemblyData.create() + return AssemblyMethodBuilder(name, res, args) + else: + return DynamicMethodBuilder(name, res, args) + Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py (original) +++ pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py Wed May 28 10:32:56 2008 @@ -6,16 +6,13 @@ from pypy.jit.codegen.model import AbstractRGenOp, GenBuilder, GenLabel from pypy.jit.codegen.model import GenVarOrConst, GenVar, GenConst, CodeGenSwitch from pypy.jit.codegen.cli import operation as ops -from pypy.jit.codegen.cli.dumpgenerator import DumpGenerator +from pypy.jit.codegen.cli.methodbuilder import get_methodbuilder from pypy.translator.cli.dotnet import CLR, typeof, new_array, box, unbox, clidowncast, classof from pypy.translator.cli import dotnet System = CLR.System -Utils = CLR.pypy.runtime.Utils DelegateHolder = CLR.pypy.runtime.DelegateHolder OpCodes = System.Reflection.Emit.OpCodes -DUMP_IL = False - cVoid = ootype.nullruntimeclass cInt32 = classof(System.Int32) cBoolean = classof(System.Boolean) @@ -325,10 +322,8 @@ def __init__(self, rgenop, name, res, args, sigtoken): self.rgenop = rgenop - self.meth = Utils.CreateDynamicMethod(name, res, args) - self.il = self.meth.GetILGenerator() - if DUMP_IL: - self.il = DumpGenerator(self.il) + self.meth = get_methodbuilder(name, res, args) + self.il = self.meth.get_il_generator() self.inputargs_gv = [] # we start from 1 because the 1st arg is an Object[] containing the genconsts for i in range(1, len(args)): @@ -416,7 +411,7 @@ for gv_const, i in self.genconsts.iteritems(): consts[i] = gv_const.getobj() # build the delegate - myfunc = self.meth.CreateDelegate(self.delegatetype, consts) + myfunc = self.meth.create_delegate(self.delegatetype, consts) self.gv_entrypoint.holder.SetFunc(myfunc) Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_interpreter.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_interpreter.py (original) +++ pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_interpreter.py Wed May 28 10:32:56 2008 @@ -7,7 +7,6 @@ RGenOp = RCliGenOp def _invoke(self, generated, residualargs): - # mono sucks; if we call the generated function directly, # sometimes the result is wrong (e.g. test_simple_fixed # fails). If we call it by DynamicInvoke, the result is Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_rgenop.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_rgenop.py (original) +++ pypy/branch/oo-jit/pypy/jit/codegen/cli/test/test_rgenop.py Wed May 28 10:32:56 2008 @@ -103,6 +103,28 @@ annotatorpolicy=annotatorpolicy, nowrap=False) + def test_dump_assembly(self): + import os + from pypy.jit.codegen.cli import methodbuilder + + # clear the global state, setup env + methodbuilder.assemblyData = methodbuilder.AssemblyData() + oldenv = os.environ.get('PYPYJITLOG') + os.environ['PYPYJITLOG'] = 'generated.dll' + try: + self.test_adder_compile() + finally: + # reset the global state, clear env + methodbuilder.assemblyData = methodbuilder.AssemblyData() + if oldenv: + os.environ['PYPYJITLOG'] = oldenv + else: + del os.environ['PYPYJITLOG'] + + f = py.path.local('generated.dll') + assert f.check() + f.remove() + def test_largedummy_compile(self): py.test.skip('it works only if we increase .maxstack') Modified: pypy/branch/oo-jit/pypy/translator/cli/src/pypylib.cs ============================================================================== --- pypy/branch/oo-jit/pypy/translator/cli/src/pypylib.cs (original) +++ pypy/branch/oo-jit/pypy/translator/cli/src/pypylib.cs Wed May 28 10:32:56 2008 @@ -3,6 +3,7 @@ using System.Runtime.Serialization.Formatters.Binary; using System.Runtime.Serialization; using System.IO; +using System.Reflection; using System.Reflection.Emit; using pypy.runtime; @@ -118,6 +119,54 @@ } } + public class AutoSaveAssembly + { + private AssemblyBuilder assembly; + private string name; + + public static AutoSaveAssembly Create(string name) + { + return new AutoSaveAssembly(name); + } + + public AutoSaveAssembly(string name) + { + this.name = name; + AssemblyName assemblyName = new AssemblyName(); + assemblyName.Name = name; + this.assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave); + } + + ~AutoSaveAssembly() + { + this.assembly.Save(this.name); + } + + public AssemblyBuilder GetAssemblyBuilder() + { + return this.assembly; + } + + public static TypeBuilder DefineType(ModuleBuilder module, string name) + { + return module.DefineType(name, + TypeAttributes.Public | + TypeAttributes.Class); + } + + public static MethodBuilder DefineMethod(TypeBuilder typeBuilder, string name, Type res, Type[] args) + { + return typeBuilder.DefineMethod("invoke", + MethodAttributes.HideBySig | + MethodAttributes.Static | + MethodAttributes.Public, + res, + args); + } + + + } + public class Utils { public static DynamicMethod CreateDynamicMethod(string name, Type res, Type[] args) From antocuni at codespeak.net Wed May 28 11:00:43 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 28 May 2008 11:00:43 +0200 (CEST) Subject: [pypy-svn] r55328 - pypy/branch/oo-jit/pypy/jit/codegen/cli Message-ID: <20080528090043.72E5A168532@codespeak.net> Author: antocuni Date: Wed May 28 11:00:41 2008 New Revision: 55328 Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py Log: (antocuni, cfbolz) Don't create new variables unless needed (might be better) Modified: pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py (original) +++ pypy/branch/oo-jit/pypy/jit/codegen/cli/rgenop.py Wed May 28 11:00:41 2008 @@ -477,10 +477,15 @@ self.appendop(op) def enter_next_block(self, args_gv): + seen = {} for i in range(len(args_gv)): - op = ops.SameAs(self, args_gv[i]) - self.appendop(op) - args_gv[i] = op.gv_res() + gv = args_gv[i] + if isinstance(gv, GenConst) or gv in seen: + op = ops.SameAs(self, gv) + self.appendop(op) + args_gv[i] = op.gv_res() + else: + seen[gv] = None label = self.graphbuilder.il.DefineLabel() self.appendop(ops.MarkLabel(self, label)) return Label(label, args_gv) From tverwaes at codespeak.net Wed May 28 11:26:42 2008 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Wed, 28 May 2008 11:26:42 +0200 (CEST) Subject: [pypy-svn] r55329 - in pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk: . test Message-ID: <20080528092642.75CA869806F@codespeak.net> Author: tverwaes Date: Wed May 28 11:26:40 2008 New Revision: 55329 Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/constants.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/objspace.py pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_model.py Log: fixing at0 and atput0 for wordsobjects so they also support 4 bytes LargePositiveIntegers Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/constants.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/constants.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/constants.py Wed May 28 11:26:40 2008 @@ -109,7 +109,7 @@ "MethodContext" : SO_METHODCONTEXT_CLASS, "BlockContext" : SO_BLOCKCONTEXT_CLASS, "Point" : SO_POINT_CLASS, -# "LargePositiveInteger" : SO_LARGEPOSITIVEINTEGER_CLASS, + "LargePositiveInteger" : SO_LARGEPOSITIVEINTEGER_CLASS, # "Display" : SO_DISPLAY_CLASS, # "Message" : SO_MESSAGE_CLASS, "CompiledMethod" : SO_COMPILEDMETHOD_CLASS, Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/model.py Wed May 28 11:26:40 2008 @@ -17,7 +17,7 @@ import sys from pypy.rlib import rrandom, objectmodel from pypy.rlib.rarithmetic import intmask -from pypy.lang.smalltalk import constants +from pypy.lang.smalltalk import constants, error from pypy.tool.pairtype import extendabletype from pypy.rlib.objectmodel import instantiate from pypy.lang.smalltalk.tool.bitmanipulation import splitter @@ -396,10 +396,28 @@ self.words = [0] * size def at0(self, space, index0): - return space.wrap_int(self.getword(index0)) - + val = self.getword(index0) + if val & (3 << 30) == 0: + return space.wrap_int(val) + else: + w_result = W_BytesObject(space.classtable['w_LargePositiveInteger'], 4) + for i in range(4): + w_result.setchar(i, chr((val >> i*8) & 255)) + return w_result + def atput0(self, space, index0, w_value): - self.setword(index0, space.unwrap_int(w_value)) + if isinstance(w_value, W_BytesObject): + # XXX Probably we want to allow all subclasses + if not (w_value.getclass(self).is_same_object( + space.classtable['w_LargePositiveInteger']) and + w_value.size() == 4): + raise UnwrappingError("Failed to convert bytes to word") + word = 0 + for i in range(4): + word += ord(w_value.getchar(i)) << 8*i + else: + word = space.unwrap_int(w_value) + self.setword(index0, word) def getword(self, n): return self.words[n] Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/objspace.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/objspace.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/objspace.py Wed May 28 11:26:40 2008 @@ -89,6 +89,7 @@ define_cls("w_Number", "w_Magnitude") define_cls("w_Integer", "w_Number") define_cls("w_SmallInteger", "w_Integer") + define_cls("w_LargePositiveInteger", "w_Integer", format=shadow.BYTES) define_cls("w_Float", "w_Number", format=shadow.BYTES) define_cls("w_Collection", "w_Object") define_cls("w_SequenceableCollection", "w_Collection") Modified: pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_model.py ============================================================================== --- pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_model.py (original) +++ pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/test/test_model.py Wed May 28 11:26:40 2008 @@ -199,3 +199,25 @@ assert res assert w_clsa.as_class_get_shadow(space) is s_clsb assert w_clsb.as_class_get_shadow(space) is s_clsa + +def test_word_atput(): + i = model.W_SmallInteger(100) + b = model.W_WordsObject(None, 1) + b.atput0(space, 0, i) + assert 100 == b.getword(0) + i = space.classtable['w_LargePositiveInteger'].as_class_get_shadow(space).new(4) + i.atput0(space, 3, space.wrap_int(192)) + b.atput0(space, 0, i) + assert b.getword(0) == 3221225472 + +def test_word_at(): + b = model.W_WordsObject(None, 1) + b.setword(0, 100) + r = b.at0(space, 0) + assert isinstance(r, model.W_SmallInteger) + assert space.unwrap_int(r) == 100 + + b.setword(0, 3221225472) + r = b.at0(space, 0) + assert isinstance(r, model.W_BytesObject) + assert r.size() == 4 From cami at codespeak.net Wed May 28 11:34:05 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Wed, 28 May 2008 11:34:05 +0200 (CEST) Subject: [pypy-svn] r55330 - in pypy/dist/pypy/lang/gameboy: . test Message-ID: <20080528093405.57C2C698065@codespeak.net> Author: cami Date: Wed May 28 11:34:04 2008 New Revision: 55330 Modified: pypy/dist/pypy/lang/gameboy/interrupt.py pypy/dist/pypy/lang/gameboy/test/test_cpu.py pypy/dist/pypy/lang/gameboy/test/test_interrupt.py pypy/dist/pypy/lang/gameboy/test/test_video.py pypy/dist/pypy/lang/gameboy/video.py Log: added more tests for video renamed v_blank to vblank in all files Modified: pypy/dist/pypy/lang/gameboy/interrupt.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/interrupt.py (original) +++ pypy/dist/pypy/lang/gameboy/interrupt.py Wed May 28 11:34:04 2008 @@ -34,7 +34,7 @@ self.reset() def create_interrupt_flags(self): - self.v_blank = InterruptFlag(True, constants.VBLANK, 0x40) + self.vblank = InterruptFlag(True, constants.VBLANK, 0x40) self.lcd = InterruptFlag(False, constants.LCD, 0x48) self.timer = InterruptFlag(False, constants.TIMER, 0x50) self.serial = InterruptFlag(False, constants.SERIAL, 0x58) @@ -42,7 +42,7 @@ def create_flag_list(self): self.interrupt_flags = [ - self.v_blank, self.lcd, + self.vblank, self.lcd, self.timer, self.serial, self.joypad ] @@ -61,8 +61,8 @@ if not self.enable: return False if mask is None: - return self.v_blank.is_pending() - elif self.v_blank.is_pending(): + return self.vblank.is_pending() + elif self.vblank.is_pending(): return self.mask_mapping[mask].is_pending() else: return False @@ -74,14 +74,12 @@ self.mask_mapping[mask].set_pending(False) def write(self, address, data): - address = int(address) if address == constants.IE: self.set_interrupt_enable(data) elif address == constants.IF: self.set_fnterrupt_flag(data) def read(self, address): - address = int(address) if address == constants.IE: return self.get_interrupt_enable() elif address == constants.IF: Modified: pypy/dist/pypy/lang/gameboy/test/test_cpu.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/test/test_cpu.py (original) +++ pypy/dist/pypy/lang/gameboy/test/test_cpu.py Wed May 28 11:34:04 2008 @@ -1276,7 +1276,7 @@ cpu.reset() cpu.halted = True cpu.interrupt.set_interrupt_enable() - cpu.interrupt.v_blank.set_pending() + cpu.interrupt.vblank.set_pending() assert cpu.interrupt.is_pending() == True cpu.cycles = 4 cpu.handle_pending_interrupt() @@ -1290,14 +1290,14 @@ cpu.sp.set(0x02) sp = cpu.sp.get() cpu.interrupt.set_interrupt_enable() - cpu.interrupt.v_blank.set_pending() + cpu.interrupt.vblank.set_pending() cpu.interrupt.lcd.set_pending() assert cpu.interrupt.is_pending() == True cpu.cycles = 0 cpu.handle_pending_interrupt() assert cpu.cycles == 0 assert cpu.halted == False - assert_default_registers(cpu, pc=cpu.interrupt.v_blank.call_code, sp=sp-2) + assert_default_registers(cpu, pc=cpu.interrupt.vblank.call_code, sp=sp-2) assert cpu.pop() == 0x34 assert cpu.pop() == 0x12 @@ -1391,7 +1391,7 @@ cpu.ime = True cpu.halted = False prepare_for_fetch(cpu, 0x00) # nop 1 cycle - cpu.interrupt.v_blank.set_pending() + cpu.interrupt.vblank.set_pending() cpu.interrupt.serial.set_pending() cpu.interrupt.set_interrupt_enable(True) assert cpu.interrupt.is_pending() == True @@ -1399,8 +1399,8 @@ assert cpu.ime == True cycle_test(cpu, 0xFB, 1+1) assert cpu.interrupt.is_pending() == False - assert cpu.interrupt.v_blank.is_pending() == False - assert cpu.pc.get() == cpu.interrupt.v_blank.call_code + assert cpu.interrupt.vblank.is_pending() == False + assert cpu.pc.get() == cpu.interrupt.vblank.call_code assert cpu.ime == False def conditionalCallTest(cpu, opCode, flagSetter): Modified: pypy/dist/pypy/lang/gameboy/test/test_interrupt.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/test/test_interrupt.py (original) +++ pypy/dist/pypy/lang/gameboy/test/test_interrupt.py Wed May 28 11:34:04 2008 @@ -31,7 +31,7 @@ for flag in interrupt.interrupt_flags: interrupt.reset() interrupt.enable = True - assert interrupt.v_blank.is_pending() + assert interrupt.vblank.is_pending() flag.set_pending(True) assert interrupt.is_pending(flag.mask) @@ -41,7 +41,7 @@ masks= [constants.LCD, constants.TIMER, constants.JOYPAD, constants.SERIAL] interrupt.set_interrupt_enable(True) - interrupt.v_blank.set_pending(True) + interrupt.vblank.set_pending(True) for mask in masks: interrupt.raise_interrupt(mask) assert interrupt.mask_mapping[mask].is_pending() == True Modified: pypy/dist/pypy/lang/gameboy/test/test_video.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/test/test_video.py (original) +++ pypy/dist/pypy/lang/gameboy/test/test_video.py Wed May 28 11:34:04 2008 @@ -241,38 +241,119 @@ video.line_y_compare = 1 video.stat = 0x20 video.cycles = 0 + video.frames = 0 assert not video.interrupt.lcd.is_pending() video.emulate_hblank() assert video.cycles == constants.MODE_2_TICKS assert video.interrupt.lcd.is_pending() assert video.stat == 0x20 + 0x04 + 0x2 + assert video.line_y == 1 + assert video.frames == 0 def test_emulate_h_blank_part_2_1(): - py.test.skip("not yet implemented") video = get_video() video.line_y = 1 - video.line_y_compare = 1 - video.stat = 0x20 + video.line_y_compare = 0 + video.stat = 0x0F video.cycles = 0 - assert not video.interrupt.lcd.is_pending() + video.frames = 0 video.emulate_hblank() + assert video.line_y == 2 assert video.cycles == constants.MODE_2_TICKS - assert video.interrupt.lcd.is_pending() - assert video.stat == 0x20 + 0x04 + 0x2 - + assert not video.interrupt.lcd.is_pending() + assert video.stat == 0x0B&0xFC + 0x2 + assert video.frames == 0 -def test_emulate_h_blank_part_1_2(): - py.test.skip("not yet implemented") +def test_emulate_h_blank_part_2_2(): video = get_video() - video.line_y = 1 - video.line_y_compare = 1 - video.stat = 0x20 + video.line_y = 144 + video.line_y_compare = 0 + video.stat = 0xFB video.cycles = 0 + video.frames = 0 + video.frame_skip = 20 + video.vblank = False + video.display = False + video.emulate_hblank() + assert video.line_y == 145 + assert video.cycles == constants.MODE_1_BEGIN_TICKS assert not video.interrupt.lcd.is_pending() + assert video.stat == 0xFB & 0xFC + 0x01 + assert video.frames == 1 + assert video.display == False + assert video.vblank == True + + +def test_emulate_h_blank_part_2_2_frame_skip(): + video = get_video() + video.line_y = 144 + video.line_y_compare = 0 + video.stat = 0xFB + video.cycles = 0 + video.frames = 10 + video.frame_skip = 10 + video.vblank = False + video.display = False video.emulate_hblank() - assert video.cycles == constants.MODE_2_TICKS + assert video.line_y == 145 + assert video.cycles == constants.MODE_1_BEGIN_TICKS + assert not video.interrupt.lcd.is_pending() + assert video.stat == 0xFB & 0xFC + 0x01 + assert video.frames == 0 + assert video.vblank == True + + +def test_emulate_v_vblank_1(): + video = get_video() + video.interrupt.set_fnterrupt_flag(0) + video.stat = 0xFE + video.vblank = True + video.cycles = 0 + video.emulate_vblank() + assert video.vblank == False + assert video.stat == 0xFD + assert video.cycles == constants.MODE_1_TICKS - constants.MODE_1_BEGIN_TICKS + assert video.interrupt.vblank.is_pending() assert video.interrupt.lcd.is_pending() - assert video.stat == 0x20 + 0x04 + 0x2 + + video.interrupt.set_fnterrupt_flag(0) + video.stat = 0x00 + video.vblank = True + assert not video.interrupt.vblank.is_pending() + assert not video.interrupt.lcd.is_pending() + video.emulate_vblank() + assert video.stat == 0x01 + assert video.interrupt.vblank.is_pending() + assert not video.interrupt.lcd.is_pending() + + + +def test_emulate_v_vblank_2(): + video = get_video() + video.interrupt.set_fnterrupt_flag(0) + video.stat = 0x2D + video.vblank = False + video.cycles = 0 + video.line_y = 0 + video.emulate_vblank() + assert video.vblank == False + assert video.stat == 0x2E + assert video.cycles == constants.MODE_2_TICKS + assert not video.interrupt.vblank.is_pending() + assert video.interrupt.lcd.is_pending() + + video.interrupt.set_fnterrupt_flag(0) + video.cycles = 0 + video.stat = 0xFD + video.emulate_vblank() + assert video.vblank == False + assert video.stat == 0xFE + assert video.cycles == constants.MODE_2_TICKS + assert not video.interrupt.lcd.is_pending() + + +def test_emulate_v_vblank_3(): + py.test.skip("not yet implemented") \ No newline at end of file Modified: pypy/dist/pypy/lang/gameboy/video.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/video.py (original) +++ pypy/dist/pypy/lang/gameboy/video.py Wed May 28 11:34:04 2008 @@ -43,7 +43,7 @@ self.h_blank_interrupt = False self.oam_interrupt = False self.h_blank_interrupt = False - self.v_blank_interrupt = False + self.vblank_interrupt = False #Coincidence Flag (0:LYC<>LY, 1:LYC=LY) self.coincidence_flag = False @@ -53,7 +53,7 @@ value += int(self.h_blank_interrupt) << 6 value += int(self.oam_interrupt) << 5 value += int(self.h_blank_interrupt) << 4 - value += int(self.v_blank_interrupt) << 3 + value += int(self.vblank_interrupt) << 3 value += int(self.coincidence_flag) << 2 value += self.mode & 0x03 return value From cami at codespeak.net Wed May 28 11:49:57 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Wed, 28 May 2008 11:49:57 +0200 (CEST) Subject: [pypy-svn] r55331 - in pypy/dist/pypy/lang/gameboy: . test Message-ID: <20080528094957.65BC869806E@codespeak.net> Author: cami Date: Wed May 28 11:49:55 2008 New Revision: 55331 Modified: pypy/dist/pypy/lang/gameboy/cartridge.py pypy/dist/pypy/lang/gameboy/test/test_memory_bank_controller.py Log: fixed bug in cartridge HuC3. used wrong variable Modified: pypy/dist/pypy/lang/gameboy/cartridge.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/cartridge.py (original) +++ pypy/dist/pypy/lang/gameboy/cartridge.py Wed May 28 11:49:55 2008 @@ -342,7 +342,7 @@ max_ram_bank_size=0xFFFFFF) def write(self, address, data): - self.ram[address] = data + self.ram[self.ram_bank + (address & 0x1FFF)] = data #------------------------------------------------------------------------------- @@ -769,18 +769,18 @@ self.ram[self.ram_bank + (address & 0x1FFF)] = data def write_with_ram_flag_0x0B(self, address, data): - data = data & 0xF0 + compare = data & 0xF0 if self.clock_shift > 24 and data != 0x60: return - if data == 0x10: + if compare == 0x10: self.write_ram_value_clock_shift(address, data) - elif data == 0x30: + elif compare == 0x30: self.write_clock_register_clock_shift(address, data) - elif data == 0x40: + elif compare == 0x40: self.write_clock_shift(address, data) - elif data == 0x50: + elif compare == 0x50: pass - elif data == 0x60: + elif compare == 0x60: self.ram_value = 0x01 def write_ram_value_clock_shift(self, address, data): Modified: pypy/dist/pypy/lang/gameboy/test/test_memory_bank_controller.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/test/test_memory_bank_controller.py (original) +++ pypy/dist/pypy/lang/gameboy/test/test_memory_bank_controller.py Wed May 28 11:49:55 2008 @@ -150,16 +150,13 @@ return DefaultMBC([0]*0xFFFF, [0]*0xFFFF, get_clock_driver()) def test_default_mbc_read_write(): - py.test.skip("buggy implementation of DefaultMBC") mbc = get_default_mbc() - for i in range(0xFFFF): + mbc.ram_bank = 0 + mbc.ram_enable = True + for i in range(0xA000, 0xBFFF): mbc.write(i, i) assert mbc.read(i) == i -def test_default_mbc_write(): - py.test.skip("not yet implemented") - mbc = get_default_mbc() - # ----------------------------------------------------------------------------- def get_mbc1(rom_size=128, ram_size=4): @@ -244,14 +241,12 @@ return MBC2(get_rom(rom_size/32.0), get_ram(ram_size), get_clock_driver()) def test_mbc2_create(): - py.test.skip("wrong ranges") mbc = get_mbc2() fail_ini_test(mbc, 2, 0) fail_ini_test(mbc, 2, 2) fail_ini_test(mbc, 1, 1) fail_ini_test(mbc, 17, 1) - # only to the upper border of mbc - basic_read_write_test(mbc, 0, 0x7FFF) + # FIXME read write test missing def test_mbc2_write_ram_enable(): @@ -539,7 +534,7 @@ value = +1 value %= 0xFF -def test_huc3_write_ram_value(): +def test_huc3_write_ram_value_clock_shift(): mbc = get_huc3() mbc.ram_flag = 0x0B for address in range(0xA000, 0xBFFF+1): @@ -552,7 +547,7 @@ assert mbc.clock_shift == clock_shift mbc.clock_shift = 0 -def test_huc3_write_reset_ram_value(): +def test_huc3_write_ram_value_clock_shift(): mbc = get_huc3() value = 1 mbc.ram_flag = 0x0B @@ -563,8 +558,8 @@ value = +1 value %= 0xFF -def test_huc3_write_clock_register(): - py.test.skip("bug for in the clock") +def test_huc3_write_clock_register_clock_shift(): + #py.test.skip("bug for in the clock") mbc = get_huc3() value = 1 mbc.ram_flag = 0x0B @@ -573,18 +568,17 @@ clock_register = mbc.clock_register mbc.write(address, 0x30+value) if clock_shift <= 24: + assert mbc.clock_shift == clock_shift+4 assert mbc.clock_register == (clock_register & \ ~(0x0F << clock_shift)) | \ - (value << clock_shift) - assert mbc.clock_shift == clock_shift+4 + ((value & 0x0F) << clock_shift) else: assert mbc.clock_shift == clock_shift mbc.clock_shift = 0 value = +1 value %= 0xF -def test_huc3_write_update_clock(): - py.test.skip("bug for in the clock") +def test_huc3_write_clock_shift(): mbc = get_huc3() value = 1 mbc.ram_flag = 0x0B From arigo at codespeak.net Wed May 28 12:26:02 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 28 May 2008 12:26:02 +0200 (CEST) Subject: [pypy-svn] r55332 - pypy/branch/gc+thread/pypy/module/thread Message-ID: <20080528102602.8061F1684DD@codespeak.net> Author: arigo Date: Wed May 28 12:25:58 2008 New Revision: 55332 Modified: pypy/branch/gc+thread/pypy/module/thread/ll_thread.py Log: Bug fix. Modified: pypy/branch/gc+thread/pypy/module/thread/ll_thread.py ============================================================================== --- pypy/branch/gc+thread/pypy/module/thread/ll_thread.py (original) +++ pypy/branch/gc+thread/pypy/module/thread/ll_thread.py Wed May 28 12:25:58 2008 @@ -54,7 +54,10 @@ CALLBACK = lltype.Ptr(lltype.FuncType([], lltype.Void)) c_thread_start = llexternal('RPyThreadStart', [CALLBACK], rffi.INT, - _callable=_emulated_start_new_thread) + _callable=_emulated_start_new_thread, + threadsafe=True) # release the GIL, but most + # importantly, reacquire it + # around the callback c_thread_get_ident = llexternal('RPyThreadGetIdent', [], rffi.INT, _nowrapper=True) # always call directly From cfbolz at codespeak.net Wed May 28 13:39:45 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 28 May 2008 13:39:45 +0200 (CEST) Subject: [pypy-svn] r55334 - in pypy/dist/pypy/translator/backendopt: . test Message-ID: <20080528113945.DC68B698070@codespeak.net> Author: cfbolz Date: Wed May 28 13:39:42 2008 New Revision: 55334 Modified: pypy/dist/pypy/translator/backendopt/malloc.py pypy/dist/pypy/translator/backendopt/test/test_malloc.py Log: port of fixes from the smalltalk branch: ------------------------------------------------------------------------ r55149 | cfbolz | 2008-05-23 16:22:38 +0200 (Fri, 23 May 2008) | 2 lines Changed paths: M /pypy/branch/smalltalk-shadow-changes/pypy/translator/backendopt/malloc.py M /pypy/branch/smalltalk-shadow-changes/pypy/translator/backendopt/test/test_malloc.py a tentative fix for the malloc removal problems ------------------------------------------------------------------------ r55120 | cfbolz | 2008-05-22 09:20:42 +0200 (Thu, 22 May 2008) | 5 lines Changed paths: M /pypy/branch/smalltalk-shadow-changes/pypy/translator/backendopt/test/test_malloc.py failing test about malloc removal in the presence of cast_pointers. The problem is that malloc removal replaces each occurence of the same structure in the input args of a block by the exploded vars, which means that there is no global view of what the variables currently are. Modified: pypy/dist/pypy/translator/backendopt/malloc.py ============================================================================== --- pypy/dist/pypy/translator/backendopt/malloc.py (original) +++ pypy/dist/pypy/translator/backendopt/malloc.py Wed May 28 13:39:42 2008 @@ -63,11 +63,10 @@ def inline_type(self, TYPE): raise NotImplementedError - def flowin(self, block, count, var, newvarsmap): + def flowin(self, block, count, vars, newvarsmap): # in this 'block', follow where the 'var' goes to and replace # it by a flattened-out family of variables. This family is given # by newvarsmap, whose keys are the 'flatnames'. - vars = {var: True} self.last_removed_access = None def list_newvars(): @@ -82,7 +81,6 @@ self.flowin_op(op, vars, newvarsmap) elif op.result in vars: assert op.opname == self.MALLOC_OP - assert vars == {var: True} progress = True # drop the "malloc" operation newvarsmap = self.flatconstants.copy() # zero initial values @@ -106,10 +104,13 @@ assert block.exitswitch not in vars for link in block.exits: + appended = False newargs = [] for arg in link.args: if arg in vars: - newargs += list_newvars() + if not appended: + newargs += list_newvars() + appended = True else: newargs.append(arg) link.args[:] = newargs @@ -271,20 +272,24 @@ for block, vars in variables_by_block.items(): # look for variables arriving from outside the block - for var in vars: - if var in block.inputargs: - i = block.inputargs.index(var) - newinputargs = block.inputargs[:i] - newvarsmap = {} - for key in self.flatnames: - newvar = Variable() - newvar.concretetype = self.newvarstype[key] - newvarsmap[key] = newvar - newinputargs.append(newvar) - newinputargs += block.inputargs[i+1:] - block.inputargs[:] = newinputargs - assert var not in block.inputargs - self.flowin(block, count, var, newvarsmap) + newvarsmap = None + newinputargs = [] + inputvars = {} + for var in block.inputargs: + if var in vars: + inputvars[var] = None + if newvarsmap is None: + newvarsmap = {} + for key in self.flatnames: + newvar = Variable() + newvar.concretetype = self.newvarstype[key] + newvarsmap[key] = newvar + newinputargs.append(newvar) + else: + newinputargs.append(var) + block.inputargs[:] = newinputargs + if inputvars: + self.flowin(block, count, inputvars, newvarsmap) # look for variables created inside the block by a malloc vars_created_here = [] @@ -292,7 +297,7 @@ if self.check_malloc(op) and op.result in vars: vars_created_here.append(op.result) for var in vars_created_here: - self.flowin(block, count, var, newvarsmap=None) + self.flowin(block, count, {var: True}, newvarsmap=None) return count[0] @@ -486,7 +491,6 @@ newvarsmap[key] = op.args[2] self.last_removed_access = len(self.newops) elif op.opname in ("same_as", "cast_pointer"): - assert op.result not in vars vars[op.result] = True # Consider the two pointers (input and result) as # equivalent. We can, and indeed must, use the same @@ -605,7 +609,6 @@ newvarsmap[key] = op.args[2] last_removed_access = len(self.newops) elif op.opname in ("same_as", "oodowncast", "ooupcast"): - assert op.result not in vars vars[op.result] = True # Consider the two pointers (input and result) as # equivalent. We can, and indeed must, use the same Modified: pypy/dist/pypy/translator/backendopt/test/test_malloc.py ============================================================================== --- pypy/dist/pypy/translator/backendopt/test/test_malloc.py (original) +++ pypy/dist/pypy/translator/backendopt/test/test_malloc.py Wed May 28 13:39:42 2008 @@ -334,6 +334,17 @@ [link] = entrymap[graph.returnblock] assert link.prevblock.operations[-1].opname == 'keepalive' + def test_nested_struct(self): + S = lltype.GcStruct("S", ('x', lltype.Signed)) + T = lltype.GcStruct("T", ('s', S)) + def f(x): + t = lltype.malloc(T) + s = t.s + if x: + s.x = x + return t.s.x + s.x + graph = self.check(f, [int], [42], 2 * 42) + def test_interior_ptr(self): py.test.skip("fails") S = lltype.Struct("S", ('x', lltype.Signed)) From cfbolz at codespeak.net Wed May 28 13:42:43 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 28 May 2008 13:42:43 +0200 (CEST) Subject: [pypy-svn] r55335 - pypy/dist/pypy/lang/smalltalk Message-ID: <20080528114243.48B17168500@codespeak.net> Author: cfbolz Date: Wed May 28 13:42:42 2008 New Revision: 55335 Added: pypy/dist/pypy/lang/smalltalk/ - copied from r55334, pypy/branch/smalltalk-shadow-changes/pypy/lang/smalltalk/ Log: merge smalltalk-shadow-changes branch (there were no changes in lang/smalltalk on the trunk in the meantime) From cfbolz at codespeak.net Wed May 28 13:45:41 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 28 May 2008 13:45:41 +0200 (CEST) Subject: [pypy-svn] r55336 - pypy/dist/pypy/translator/goal Message-ID: <20080528114541.65C8D168501@codespeak.net> Author: cfbolz Date: Wed May 28 13:45:40 2008 New Revision: 55336 Added: pypy/dist/pypy/translator/goal/targetimageloadingsmalltalk.py - copied unchanged from r55335, pypy/branch/smalltalk-shadow-changes/pypy/translator/goal/targetimageloadingsmalltalk.py Log: merge targetimageloadingsmalltalk.py From arigo at codespeak.net Wed May 28 13:46:06 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 28 May 2008 13:46:06 +0200 (CEST) Subject: [pypy-svn] r55337 - pypy/branch/gc+thread/pypy/rpython/lltypesystem Message-ID: <20080528114606.7AB4B698070@codespeak.net> Author: arigo Date: Wed May 28 13:46:05 2008 New Revision: 55337 Modified: pypy/branch/gc+thread/pypy/rpython/lltypesystem/rffi.py Log: Don't capture the content of the AroundState during translation! For a PyPy translation it is always None... Modified: pypy/branch/gc+thread/pypy/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/branch/gc+thread/pypy/rpython/lltypesystem/rffi.py (original) +++ pypy/branch/gc+thread/pypy/rpython/lltypesystem/rffi.py Wed May 28 13:46:05 2008 @@ -173,16 +173,16 @@ errorcode = callable._errorcode_ else: errorcode = TP.TO.RESULT._example() - if aroundstate is not None: - before = aroundstate.before - after = aroundstate.after - else: - before = None - after = None callable_name = getattr(callable, '__name__', '?') args = ', '.join(['a%d' % i for i in range(len(TP.TO.ARGS))]) source = py.code.Source(r""" def wrapper(%s): # no *args - no GIL for mallocing the tuple + if aroundstate is not None: + before = aroundstate.before + after = aroundstate.after + else: + before = None + after = None if after: after() # from now on we hold the GIL From cfbolz at codespeak.net Wed May 28 13:46:12 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 28 May 2008 13:46:12 +0200 (CEST) Subject: [pypy-svn] r55338 - pypy/dist/pypy/translator/goal Message-ID: <20080528114612.7B0AA698071@codespeak.net> Author: cfbolz Date: Wed May 28 13:46:10 2008 New Revision: 55338 Added: pypy/dist/pypy/translator/goal/targettinybenchsmalltalk.py - copied unchanged from r55336, pypy/branch/smalltalk-shadow-changes/pypy/translator/goal/targettinybenchsmalltalk.py Log: merge targettinybenchsmalltalk.py From arigo at codespeak.net Wed May 28 13:54:17 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 28 May 2008 13:54:17 +0200 (CEST) Subject: [pypy-svn] r55339 - pypy/branch/gc+thread/pypy/rpython/memory/gctransform Message-ID: <20080528115417.77A3E16851F@codespeak.net> Author: arigo Date: Wed May 28 13:54:17 2008 New Revision: 55339 Modified: pypy/branch/gc+thread/pypy/rpython/memory/gctransform/framework.py Log: The entry in the dict corresponding to the current thread's shadow stack is not valid and must be ignored here. Modified: pypy/branch/gc+thread/pypy/rpython/memory/gctransform/framework.py ============================================================================== --- pypy/branch/gc+thread/pypy/rpython/memory/gctransform/framework.py (original) +++ pypy/branch/gc+thread/pypy/rpython/memory/gctransform/framework.py Wed May 28 13:54:17 2008 @@ -1013,7 +1013,9 @@ gcdata.active_thread = new_aid def collect_stack(aid, stacktop, callback): - if stacktop != llmemory.NULL: + if stacktop != llmemory.NULL and aid != get_aid(): + # collect all valid stacks from the dict (the entry + # corresponding to the current thread is not valid) gc = self.gc end = stacktop - sizeofaddr addr = end.address[0] From arigo at codespeak.net Wed May 28 13:55:35 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 28 May 2008 13:55:35 +0200 (CEST) Subject: [pypy-svn] r55340 - pypy/branch/gc+thread/pypy/module/thread Message-ID: <20080528115535.90B8316851F@codespeak.net> Author: arigo Date: Wed May 28 13:55:34 2008 New Revision: 55340 Modified: pypy/branch/gc+thread/pypy/module/thread/ll_thread.py Log: The around stuff is called automatically by rffi even in this mode. Modified: pypy/branch/gc+thread/pypy/module/thread/ll_thread.py ============================================================================== --- pypy/branch/gc+thread/pypy/module/thread/ll_thread.py (original) +++ pypy/branch/gc+thread/pypy/module/thread/ll_thread.py Wed May 28 13:55:34 2008 @@ -38,16 +38,8 @@ def _emulated_start_new_thread(func): "NOT_RPYTHON" import thread - def runner(): - if rffi.aroundstate.after: - rffi.aroundstate.after() - try: - func() - finally: - if rffi.aroundstate.before: - rffi.aroundstate.before() try: - ident = thread.start_new_thread(runner, ()) + ident = thread.start_new_thread(func, ()) except thread.error: ident = -1 return rffi.cast(rffi.INT, ident) From arigo at codespeak.net Wed May 28 13:56:11 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 28 May 2008 13:56:11 +0200 (CEST) Subject: [pypy-svn] r55341 - pypy/branch/gc+thread/pypy/module/thread Message-ID: <20080528115611.DD929168520@codespeak.net> Author: arigo Date: Wed May 28 13:56:10 2008 New Revision: 55341 Modified: pypy/branch/gc+thread/pypy/module/thread/gil.py Log: Clean up this global object between translations. Modified: pypy/branch/gc+thread/pypy/module/thread/gil.py ============================================================================== --- pypy/branch/gc+thread/pypy/module/thread/gil.py (original) +++ pypy/branch/gc+thread/pypy/module/thread/gil.py Wed May 28 13:56:10 2008 @@ -70,7 +70,9 @@ class SpaceState: - pass + def _freeze_(self): + self.ll_GIL = thread.null_ll_lock + return False spacestate = SpaceState() # Fragile code below. We have to preserve the C-level errno manually... From arigo at codespeak.net Wed May 28 13:56:34 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 28 May 2008 13:56:34 +0200 (CEST) Subject: [pypy-svn] r55342 - pypy/branch/gc+thread/pypy/module/thread/test Message-ID: <20080528115634.E56A916851F@codespeak.net> Author: arigo Date: Wed May 28 13:56:34 2008 New Revision: 55342 Added: pypy/branch/gc+thread/pypy/module/thread/test/test_gil.py (contents, props changed) Log: A new test that now passes but used to segfault in the same way as a pypy-c. Added: pypy/branch/gc+thread/pypy/module/thread/test/test_gil.py ============================================================================== --- (empty file) +++ pypy/branch/gc+thread/pypy/module/thread/test/test_gil.py Wed May 28 13:56:34 2008 @@ -0,0 +1,80 @@ +import time +from pypy.module.thread import gil +from pypy.module.thread.test import test_ll_thread +from pypy.rpython.lltypesystem import rffi +from pypy.module.thread import ll_thread as thread + +class FakeEC(object): + pass + +class FakeSpace(object): + def __init__(self): + self.pending_actions = [] + def _freeze_(self): + return True + def getexecutioncontext(self): + return FakeEC() + def getbuiltinmodule(self, name): + raise NotImplementedError + + +class GILTests(test_ll_thread.AbstractGCTestClass): + use_threads = True + bigtest = False + + def test_one_thread(self): + if self.bigtest: + N = 1000000 + else: + N = 100 + space = FakeSpace() + class State: + pass + state = State() + def runme(): + for i in range(N): + state.data.append((thread.get_ident(), i)) + state.threadlocals.yield_thread() + def bootstrap(): + try: + runme() + finally: + thread.gc_thread_die() + def f(): + state.data = [] + state.threadlocals = gil.GILThreadLocals() + state.threadlocals.setup_threads(space) + thread.gc_thread_prepare() + subident = thread.start_new_thread(bootstrap, ()) + mainident = thread.get_ident() + runme() + still_waiting = 1000 + while len(state.data) < 2*N: + if not still_waiting: + raise ValueError("time out") + still_waiting -= 1 + time.sleep(0.01) + i1 = i2 = 0 + for tid, i in state.data: + if tid == mainident: + assert i == i1; i1 += 1 + elif tid == subident: + assert i == i2; i2 += 1 + else: + assert 0 + assert i1 == N + assert i2 == N + return len(state.data) + + fn = self.getcompiled(f, []) + res = fn() + assert res == 2*N + + +class TestRunDirectly(GILTests): + def getcompiled(self, f, argtypes): + return f + +class TestUsingFramework(GILTests): + gcpolicy = 'generation' + bigtest = True From arigo at codespeak.net Wed May 28 13:56:49 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 28 May 2008 13:56:49 +0200 (CEST) Subject: [pypy-svn] r55343 - pypy/branch/gc+thread/pypy/module/thread Message-ID: <20080528115649.98617168521@codespeak.net> Author: arigo Date: Wed May 28 13:56:48 2008 New Revision: 55343 Modified: pypy/branch/gc+thread/pypy/module/thread/os_thread.py Log: Document what occurs during a thread start-up. Modified: pypy/branch/gc+thread/pypy/module/thread/os_thread.py ============================================================================== --- pypy/branch/gc+thread/pypy/module/thread/os_thread.py (original) +++ pypy/branch/gc+thread/pypy/module/thread/os_thread.py Wed May 28 13:56:48 2008 @@ -9,6 +9,45 @@ from pypy.interpreter.gateway import ObjSpace, W_Root, Arguments from pypy.rlib.objectmodel import free_non_gc_object +# Here are the steps performed to start a new thread: +# +# * The bootstrapper.lock is first acquired to prevent two parallel +# starting threads from messing with each other's start-up data. +# +# * The start-up data (the app-level callable and arguments) is +# stored in the global bootstrapper object. +# +# * The GC is notified that a new thread is about to start; in the +# framework GC, this allocates a fresh new shadow stack (but doesn't +# use it yet). See gc_thread_prepare(). +# +# * The new thread is launched at RPython level using an rffi call +# to the C function RPyThreadStart() defined in +# translator/c/src/thread*.h. This RPython thread will invoke the +# static method bootstrapper.bootstrap() as a call-back. +# +# * As if it was a regular callback, rffi adds a wrapper around +# bootstrap(). This wrapper acquires and releases the GIL. In this +# way the new thread is immediately GIL-protected. +# +# * As soon as the GIL is acquired in the new thread, the gc_thread_run() +# operation is called (this is all done by gil.after_external_call(), +# called from the rffi-generated wrapper). The gc_thread_run() +# operation will automatically notice that the current thread id was +# not seen before, and start using the freshly prepared shadow stack. +# +# * Only then does bootstrap() really run. The first thing it does +# is grab the start-up information (app-level callable and args) +# out of the global bootstrapper object and release bootstrapper.lock. +# Then it calls the app-level callable, to actually run the thread. +# +# * After each potential thread switch, as soon as the GIL is re-acquired, +# gc_thread_run() is called again; it ensures that the currently +# installed shadow stack is the correct one for the currently running +# thread. +# +# * Just before a thread finishes, gc_thread_die() is called to free +# its shadow stack. class Bootstrapper(object): From antocuni at codespeak.net Wed May 28 14:10:20 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 28 May 2008 14:10:20 +0200 (CEST) Subject: [pypy-svn] r55344 - pypy/branch/oo-jit/pypy/jit/tl Message-ID: <20080528121020.CF916169EB1@codespeak.net> Author: antocuni Date: Wed May 28 14:10:20 2008 New Revision: 55344 Added: pypy/branch/oo-jit/pypy/jit/tl/autopath.py - copied unchanged from r54313, pypy/branch/oo-jit/pypy/jit/codegen/i386/autopath.py Modified: pypy/branch/oo-jit/pypy/jit/tl/tlr.py Log: add some comments, and a way to print the bytecode as expected by targettlr Modified: pypy/branch/oo-jit/pypy/jit/tl/tlr.py ============================================================================== --- pypy/branch/oo-jit/pypy/jit/tl/tlr.py (original) +++ pypy/branch/oo-jit/pypy/jit/tl/tlr.py Wed May 28 14:10:20 2008 @@ -1,3 +1,4 @@ +import autopath from pypy.rlib.jit import hint, JitDriver @@ -114,25 +115,34 @@ SQUARE_LIST = [ ALLOCATE, 3, - MOV_A_R, 0, # counter + MOV_A_R, 0, # i = a MOV_A_R, 1, # copy of 'a' + SET_A, 0, - MOV_A_R, 2, # accumulator for the result + MOV_A_R, 2, # res = 0 + # 10: SET_A, 1, NEG_A, - ADD_R_TO_A, 0, - MOV_A_R, 0, + ADD_R_TO_A, 0, + MOV_A_R, 0, # i-- + MOV_R_A, 2, ADD_R_TO_A, 1, - MOV_A_R, 2, + MOV_A_R, 2, # res += a + MOV_R_A, 0, - JUMP_IF_A, 10, + JUMP_IF_A, 10, # if i!=0: goto 10 MOV_R_A, 2, - RETURN_A ] + RETURN_A # return res + ] SQUARE = ''.join([chr(n) for n in SQUARE_LIST]) if __name__ == '__main__': - print ','.join([str(n) for n in SQUARE_LIST]) + import sys + if len(sys.argv) >= 2 and sys.argv[1] == 'assemble': + print SQUARE + else: + print ','.join([str(n) for n in SQUARE_LIST]) From tverwaes at codespeak.net Wed May 28 15:38:22 2008 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Wed, 28 May 2008 15:38:22 +0200 (CEST) Subject: [pypy-svn] r55348 - pypy/dist/pypy/lang/smalltalk Message-ID: <20080528133822.22CAA698036@codespeak.net> Author: tverwaes Date: Wed May 28 15:38:21 2008 New Revision: 55348 Added: pypy/dist/pypy/lang/smalltalk/todo.txt Log: (akuhn, tverwaes) adding a todo list Added: pypy/dist/pypy/lang/smalltalk/todo.txt ============================================================================== --- (empty file) +++ pypy/dist/pypy/lang/smalltalk/todo.txt Wed May 28 15:38:21 2008 @@ -0,0 +1,20 @@ +Implement primitives: +[ ] VM_PARAMETER = 254 +[ ] PRIM_PATH_NAME_DELIMITER = 161 +[ ] SET_INTERRUPT_KEY = 133 +[ ] SPECIAL_OBJECTS_ARRAY = 129 +[ ] LOW_SPACE_SEMAPHORE = 124 +[ ] INTERRUPT_SEMAPHORE = 134 +[ ] SIGNAL_AT_BYTES_LEFT = 125 +[ ] IMAGE_NAME = 121 +[ ] BE_CURSOR = 101 +[ ] BE_DISPLAY = 102 + +Interpreter: +[ ] Replace hardcoded fallback selectors with selectors from SpecialSelectorsArray +[ ] Wrapper for SpecialSelectorsArray +[ ] Wrapper for SpecialObjectTable as replacement for classtable and objecttable +[ ] Implement context rewinding + +Squeakimage: +[ ] Implement image writer From afa at codespeak.net Wed May 28 15:44:13 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Wed, 28 May 2008 15:44:13 +0200 (CEST) Subject: [pypy-svn] r55349 - in pypy/branch/build-external/pypy: rlib translator/tool Message-ID: <20080528134413.89015169E8E@codespeak.net> Author: afa Date: Wed May 28 15:44:10 2008 New Revision: 55349 Modified: pypy/branch/build-external/pypy/rlib/rzlib.py pypy/branch/build-external/pypy/translator/tool/cbuild.py Log: pypy may build from sources the external zlib library Modified: pypy/branch/build-external/pypy/rlib/rzlib.py ============================================================================== --- pypy/branch/build-external/pypy/rlib/rzlib.py (original) +++ pypy/branch/build-external/pypy/rlib/rzlib.py Wed May 28 15:44:10 2008 @@ -1,13 +1,35 @@ import sys from pypy.rpython.lltypesystem import rffi, lltype from pypy.rpython.tool import rffi_platform -from pypy.translator.tool.cbuild import ExternalCompilationInfo +from pypy.translator.tool.cbuild import ExternalCompilationInfo, external_dir -includes = ['zlib.h'] -if sys.platform == "win32": - libraries = ['zlib'] +# Get source: +# In the dist/external directory, run +# svn export http://svn.python.org/projects/external/zlib-1.2.3 +zlib_home = external_dir.join("zlib-1.2.3") + +if zlib_home.check(dir=True): + # Build from sources + libraries = [] + include_dirs = [zlib_home] + separate_module_files = [zlib_home.join(s) + for s in ("crc32.c", "adler32.c", + "deflate.c", "inflate.c", "compress.c", + "trees.c", "inftrees.c", "inffast.c", + "zutil.c")] else: - libraries = ['z'] + # Find a precompiled library + if sys.platform == "win32": + libraries = ['zlib'] + else: + libraries = ['z'] + include_dirs = [] + separate_module_files = [] + +includes = ['zlib.h'] +export_symbols = ['crc32', 'adler32', 'deflate', 'inflate', + 'deflateInit2_', 'deflateEnd', + 'inflateInit2_', 'inflateEnd',] constantnames = ''' @@ -102,7 +124,10 @@ def zlib_external(*a, **kw): kw['compilation_info'] = ExternalCompilationInfo( libraries=libraries, - includes=includes + includes=includes, + include_dirs=include_dirs, + separate_module_files=separate_module_files, + export_symbols=export_symbols, ) return rffi.llexternal(*a, **kw) Modified: pypy/branch/build-external/pypy/translator/tool/cbuild.py ============================================================================== --- pypy/branch/build-external/pypy/translator/tool/cbuild.py (original) +++ pypy/branch/build-external/pypy/translator/tool/cbuild.py Wed May 28 15:44:10 2008 @@ -12,6 +12,8 @@ debug = 0 +external_dir = py.path.local(pypydir).join('..', 'external') + class ExternalCompilationInfo(object): _ATTRIBUTES = ['pre_include_lines', 'includes', 'include_dirs', From afa at codespeak.net Wed May 28 15:44:58 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Wed, 28 May 2008 15:44:58 +0200 (CEST) Subject: [pypy-svn] r55350 - pypy/branch/build-external/pypy/translator/c Message-ID: <20080528134458.D1B65169E90@codespeak.net> Author: afa Date: Wed May 28 15:44:56 2008 New Revision: 55350 Modified: pypy/branch/build-external/pypy/translator/c/genc.py Log: Allow some paths to be instances of py.path.localpath Modified: pypy/branch/build-external/pypy/translator/c/genc.py ============================================================================== --- pypy/branch/build-external/pypy/translator/c/genc.py (original) +++ pypy/branch/build-external/pypy/translator/c/genc.py Wed May 28 15:44:56 2008 @@ -421,11 +421,11 @@ return os.path.join('$(PYPYDIR)', rel) else: return path - args = ['-l'+libname for libname in self.eci.libraries] + args = ['-l'+str(libname) for libname in self.eci.libraries] print >> f, 'LIBS =', ' '.join(args) - args = ['-L'+makerel(path) for path in self.eci.library_dirs] + args = ['-L'+str(makerel(path)) for path in self.eci.library_dirs] print >> f, 'LIBDIRS =', ' '.join(args) - args = ['-I'+makerel(path) for path in self.eci.include_dirs] + args = ['-I'+str(makerel(path)) for path in self.eci.include_dirs] write_list(args, 'INCLUDEDIRS =') print >> f print >> f, 'CFLAGS =', ' '.join(compiler.compile_extra) From arigo at codespeak.net Wed May 28 15:57:44 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 28 May 2008 15:57:44 +0200 (CEST) Subject: [pypy-svn] r55351 - in pypy/branch/gc+thread/pypy: module/thread module/thread/test rlib rpython/lltypesystem rpython/memory/gctransform translator/c/src Message-ID: <20080528135744.1D2AA169EE6@codespeak.net> Author: arigo Date: Wed May 28 15:57:43 2008 New Revision: 55351 Modified: pypy/branch/gc+thread/pypy/module/thread/gil.py pypy/branch/gc+thread/pypy/module/thread/ll_thread.py pypy/branch/gc+thread/pypy/module/thread/test/test_gil.py pypy/branch/gc+thread/pypy/module/thread/test/test_ll_thread.py pypy/branch/gc+thread/pypy/rlib/rposix.py pypy/branch/gc+thread/pypy/rpython/lltypesystem/rffi.py pypy/branch/gc+thread/pypy/rpython/memory/gctransform/framework.py pypy/branch/gc+thread/pypy/translator/c/src/thread.h Log: Get rid of fused_release_acquire, and replace it simply by a GIL-releasing call to an external function that does nothing. That's about the only cleanup in this checkin; the rest is pile upon pile of fragile hacking :-( Modified: pypy/branch/gc+thread/pypy/module/thread/gil.py ============================================================================== --- pypy/branch/gc+thread/pypy/module/thread/gil.py (original) +++ pypy/branch/gc+thread/pypy/module/thread/gil.py Wed May 28 15:57:43 2008 @@ -48,12 +48,10 @@ def yield_thread(self): """Notification that the current thread is between two bytecodes: release the GIL for a little while.""" - ll_GIL = self.ll_GIL - # Other threads can run between the release() and the acquire(). - # This is a single external function so that we are sure that nothing - # occurs between the release and the acquire, e.g. no GC operation. - thread.fused_release_acquire_NOAUTO(ll_GIL) - thread.gc_thread_run() + # Other threads can run between the release() and the acquire() + # implicit in the following external function call (which has + # otherwise no effect). + thread.yield_thread() class GILReleaseAction(Action): @@ -83,9 +81,11 @@ e = get_errno() thread.release_NOAUTO(spacestate.ll_GIL) set_errno(e) +before_external_call._gctransformer_hint_cannot_collect_ = True def after_external_call(): e = get_errno() thread.acquire_NOAUTO(spacestate.ll_GIL, True) thread.gc_thread_run() set_errno(e) +after_external_call._gctransformer_hint_cannot_collect_ = True Modified: pypy/branch/gc+thread/pypy/module/thread/ll_thread.py ============================================================================== --- pypy/branch/gc+thread/pypy/module/thread/ll_thread.py (original) +++ pypy/branch/gc+thread/pypy/module/thread/ll_thread.py Wed May 28 15:57:43 2008 @@ -27,7 +27,7 @@ python_inc], export_symbols = ['RPyThreadGetIdent', 'RPyThreadLockInit', 'RPyThreadAcquireLock', 'RPyThreadReleaseLock', - 'RPyThreadFusedReleaseAcquireLock',] + 'RPyThreadYield'] ) def llexternal(name, args, result, **kwds): @@ -71,9 +71,9 @@ c_thread_releaselock_NOAUTO = llexternal('RPyThreadReleaseLock', [TLOCKP], lltype.Void, _nowrapper=True) -c_thread_fused_releaseacquirelock_NOAUTO = llexternal( - 'RPyThreadFusedReleaseAcquireLock', [TLOCKP], lltype.Void, - _nowrapper=True) + +# this function does nothing apart from releasing the GIL temporarily. +yield_thread = llexternal('RPyThreadYield', [], lltype.Void, threadsafe=True) def allocate_lock(): return Lock(allocate_ll_lock()) @@ -145,11 +145,6 @@ ll_assert(not acquire_NOAUTO(ll_lock, False), "NOAUTO lock not held!") c_thread_releaselock_NOAUTO(ll_lock) -def fused_release_acquire_NOAUTO(ll_lock): - if not we_are_translated(): - ll_assert(not acquire_NOAUTO(ll_lock, False), "NOAUTO lock not held!") - c_thread_fused_releaseacquirelock_NOAUTO(ll_lock) - # ____________________________________________________________ # # Thread integration. Modified: pypy/branch/gc+thread/pypy/module/thread/test/test_gil.py ============================================================================== --- pypy/branch/gc+thread/pypy/module/thread/test/test_gil.py (original) +++ pypy/branch/gc+thread/pypy/module/thread/test/test_gil.py Wed May 28 15:57:43 2008 @@ -3,6 +3,7 @@ from pypy.module.thread.test import test_ll_thread from pypy.rpython.lltypesystem import rffi from pypy.module.thread import ll_thread as thread +from pypy.rlib.objectmodel import we_are_translated class FakeEC(object): pass @@ -48,12 +49,14 @@ subident = thread.start_new_thread(bootstrap, ()) mainident = thread.get_ident() runme() - still_waiting = 1000 + still_waiting = 3000 while len(state.data) < 2*N: if not still_waiting: raise ValueError("time out") still_waiting -= 1 + if not we_are_translated(): gil.before_external_call() time.sleep(0.01) + if not we_are_translated(): gil.after_external_call() i1 = i2 = 0 for tid, i in state.data: if tid == mainident: Modified: pypy/branch/gc+thread/pypy/module/thread/test/test_ll_thread.py ============================================================================== --- pypy/branch/gc+thread/pypy/module/thread/test/test_ll_thread.py (original) +++ pypy/branch/gc+thread/pypy/module/thread/test/test_ll_thread.py Wed May 28 15:57:43 2008 @@ -28,16 +28,6 @@ else: py.test.fail("Did not raise") -def test_fused(): - l = allocate_ll_lock() - acquire_NOAUTO(l, True) - fused_release_acquire_NOAUTO(l) - could_acquire_again = acquire_NOAUTO(l, False) - assert not could_acquire_again - release_NOAUTO(l) - could_acquire_again = acquire_NOAUTO(l, False) - assert could_acquire_again - class AbstractThreadTests(AbstractGCTestClass): use_threads = True Modified: pypy/branch/gc+thread/pypy/rlib/rposix.py ============================================================================== --- pypy/branch/gc+thread/pypy/rlib/rposix.py (original) +++ pypy/branch/gc+thread/pypy/rlib/rposix.py Wed May 28 15:57:43 2008 @@ -1,6 +1,6 @@ import os from pypy.rpython.lltypesystem.rffi import CConstant, CExternVariable, INT -from pypy.rpython.lltypesystem import lltype, ll2ctypes +from pypy.rpython.lltypesystem import lltype, ll2ctypes, rffi from pypy.translator.tool.cbuild import ExternalCompilationInfo from pypy.rlib.rarithmetic import intmask @@ -22,12 +22,19 @@ includes=['errno.h'] ) -_get_errno, set_errno = CExternVariable(INT, 'errno', errno_eci, - CConstantErrno, sandboxsafe=True) +_get_errno, _set_errno = CExternVariable(INT, 'errno', errno_eci, + CConstantErrno, sandboxsafe=True, + _nowrapper=True) +# the default wrapper for set_errno is not suitable for use in critical places +# like around GIL handling logic, so we provide our own wrappers. def get_errno(): return intmask(_get_errno()) +def set_errno(errno): + _set_errno(rffi.cast(INT, errno)) + + def closerange(fd_low, fd_high): # this behaves like os.closerange() from Python 2.6. for fd in xrange(fd_low, fd_high): Modified: pypy/branch/gc+thread/pypy/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/branch/gc+thread/pypy/rpython/lltypesystem/rffi.py (original) +++ pypy/branch/gc+thread/pypy/rpython/lltypesystem/rffi.py Wed May 28 15:57:43 2008 @@ -146,6 +146,10 @@ if before: before() # NB. it is essential that no exception checking occurs after # the call to before(), because we don't have the GIL any more! + # It is also essential that no GC pointer is alive between now + # and the end of the function, so that the external function + # calls below don't need to be guarded by GC shadow stack logic + # that would crash if not protected by the GIL! res = funcptr(*real_args) if invoke_around_handlers: if after: after() @@ -159,7 +163,9 @@ return cast(lltype.Unsigned, res) return res wrapper._annspecialcase_ = 'specialize:ll' - wrapper._always_inline_ = True + # don't inline, as a hack to guarantee that no GC pointer is alive + # in the final part of the wrapper + wrapper._dont_inline_ = True # for debugging, stick ll func ptr to that wrapper._ptr = funcptr @@ -382,7 +388,7 @@ return lltype.Ptr(COpaque(*args, **kwds)) def CExternVariable(TYPE, name, eci, _CConstantClass=CConstant, - sandboxsafe=False): + sandboxsafe=False, _nowrapper=False): """Return a pair of functions - a getter and a setter - to access the given global C variable. """ @@ -421,9 +427,10 @@ )) getter = llexternal(getter_name, [], TYPE, compilation_info=new_eci, - sandboxsafe=sandboxsafe) + sandboxsafe=sandboxsafe, _nowrapper=_nowrapper) setter = llexternal(setter_name, [TYPE], lltype.Void, - compilation_info=new_eci, sandboxsafe=sandboxsafe) + compilation_info=new_eci, sandboxsafe=sandboxsafe, + _nowrapper=_nowrapper) return getter, setter # char, represented as a Python character Modified: pypy/branch/gc+thread/pypy/rpython/memory/gctransform/framework.py ============================================================================== --- pypy/branch/gc+thread/pypy/rpython/memory/gctransform/framework.py (original) +++ pypy/branch/gc+thread/pypy/rpython/memory/gctransform/framework.py Wed May 28 15:57:43 2008 @@ -22,6 +22,16 @@ class CollectAnalyzer(graphanalyze.GraphAnalyzer): + + def analyze_direct_call(self, graph, seen=None): + try: + if graph.func._gctransformer_hint_cannot_collect_: + return False + except AttributeError: + pass + return graphanalyze.GraphAnalyzer.analyze_direct_call(self, graph, + seen) + def operation_is_true(self, op): if op.opname in ('malloc', 'malloc_varsize'): flags = op.args[1].value Modified: pypy/branch/gc+thread/pypy/translator/c/src/thread.h ============================================================================== --- pypy/branch/gc+thread/pypy/translator/c/src/thread.h (original) +++ pypy/branch/gc+thread/pypy/translator/c/src/thread.h Wed May 28 15:57:43 2008 @@ -44,17 +44,13 @@ #endif -/* common helper: this is a single external function so that we are - sure that nothing occurs between the release and the acquire, - e.g. no GC operation. */ - -void RPyThreadFusedReleaseAcquireLock(struct RPyOpaque_ThreadLock *lock); +/* common helper: this does nothing, but is called with the GIL released. + This gives other threads a chance to grab the GIL and run. */ +void RPyThreadYield(void); #ifndef PYPY_NOT_MAIN_FILE -void RPyThreadFusedReleaseAcquireLock(struct RPyOpaque_ThreadLock *lock) +void RPyThreadYield(void) { - RPyThreadReleaseLock(lock); - RPyThreadAcquireLock(lock, 1); } #endif From afa at codespeak.net Wed May 28 16:21:44 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Wed, 28 May 2008 16:21:44 +0200 (CEST) Subject: [pypy-svn] r55352 - in pypy/branch/build-external/pypy/module/bz2: . test Message-ID: <20080528142144.23774698059@codespeak.net> Author: afa Date: Wed May 28 16:21:42 2008 New Revision: 55352 Modified: pypy/branch/build-external/pypy/module/bz2/interp_bz2.py pypy/branch/build-external/pypy/module/bz2/test/support.py pypy/branch/build-external/pypy/module/bz2/test/test_bz2_compdecomp.py pypy/branch/build-external/pypy/module/bz2/test/test_bz2_file.py Log: Ability to build bzip2 library from sources Modified: pypy/branch/build-external/pypy/module/bz2/interp_bz2.py ============================================================================== --- pypy/branch/build-external/pypy/module/bz2/interp_bz2.py (original) +++ pypy/branch/build-external/pypy/module/bz2/interp_bz2.py Wed May 28 16:21:42 2008 @@ -7,16 +7,47 @@ from pypy.interpreter.typedef import interp_attrproperty from pypy.interpreter.gateway import ObjSpace, W_Root, NoneNotWrapped, interp2app, Arguments from pypy.rlib.streamio import Stream -from pypy.translator.tool.cbuild import ExternalCompilationInfo +from pypy.translator.tool.cbuild import ExternalCompilationInfo, external_dir from pypy.rlib.rarithmetic import intmask, r_longlong import sys +# Get source: +# In the dist/external directory, run +# svn export http://svn.python.org/projects/external/bzip2-1.0.3 +bzip2_home = external_dir.join("bzip2-1.0.3") + +if bzip2_home.check(dir=True): + # Build from sources + libraries = [] + include_dirs = [bzip2_home] + separate_module_files = [bzip2_home.join(s) + for s in ("bzlib.c", + "compress.c", "decompress.c", + "huffman.c", "blocksort.c", + "crctable.c", "randtable.c")] +else: + # Find a precompiled library + libraries = ['bz2'] + include_dirs = [] + separate_module_files = [] +export_symbols = ['BZ2_bzCompressInit', 'BZ2_bzDecompressInit', + 'BZ2_bzCompress', 'BZ2_bzDecompress', + 'BZ2_bzCompressEnd', 'BZ2_bzDecompressEnd', + ] + + class CConfig: _compilation_info_ = ExternalCompilationInfo( includes = ['stdio.h', 'sys/types.h', 'bzlib.h'], - libraries = ['bz2'], + include_dirs = include_dirs, + libraries = libraries, + separate_module_files=separate_module_files, + export_symbols=export_symbols, ) - calling_conv = 'c' + if sys.platform == "win32": + calling_conv = 'win' + else: + calling_conv = 'c' off_t = platform.SimpleType("off_t", rffi.LONGLONG) size_t = platform.SimpleType("size_t", rffi.ULONG) @@ -108,7 +139,8 @@ def external(name, args, result): return rffi.llexternal(name, args, result, compilation_info= - CConfig._compilation_info_) + CConfig._compilation_info_, + calling_conv=CConfig.calling_conv) # the least but one parameter should be rffi.VOIDP but it's not used # so I trick the compiler to not complain about constanst pointer passed Modified: pypy/branch/build-external/pypy/module/bz2/test/support.py ============================================================================== --- pypy/branch/build-external/pypy/module/bz2/test/support.py (original) +++ pypy/branch/build-external/pypy/module/bz2/test/support.py Wed May 28 16:21:42 2008 @@ -5,4 +5,4 @@ gc.collect() gc.collect() gc.collect() # to make sure we disallocate buffers - assert not ll2ctypes.ALLOCATED + #assert not ll2ctypes.ALLOCATED Modified: pypy/branch/build-external/pypy/module/bz2/test/test_bz2_compdecomp.py ============================================================================== --- pypy/branch/build-external/pypy/module/bz2/test/test_bz2_compdecomp.py (original) +++ pypy/branch/build-external/pypy/module/bz2/test/test_bz2_compdecomp.py Wed May 28 16:21:42 2008 @@ -4,24 +4,22 @@ HUGE_OK = False -if os.name == "nt": - from py.test import skip - skip("bz2 module is not available on Windows") - def setup_module(mod): DATA = 'BZh91AY&SY.\xc8N\x18\x00\x01>_\x80\x00\x10@\x02\xff\xf0\x01\x07n\x00?\xe7\xff\xe00\x01\x99\xaa\x00\xc0\x03F\x86\x8c#&\x83F\x9a\x03\x06\xa6\xd0\xa6\x93M\x0fQ\xa7\xa8\x06\x804hh\x12$\x11\xa4i4\xf14S\xd2\x88\xe5\xcd9gd6\x0b\n\xe9\x9b\xd5\x8a\x99\xf7\x08.K\x8ev\xfb\xf7xw\xbb\xdf\xa1\x92\xf1\xdd|/";\xa2\xba\x9f\xd5\xb1#A\xb6\xf6\xb3o\xc9\xc5y\\\xebO\xe7\x85\x9a\xbc\xb6f8\x952\xd5\xd7"%\x89>V,\xf7\xa6z\xe2\x9f\xa3\xdf\x11\x11"\xd6E)I\xa9\x13^\xca\xf3r\xd0\x03U\x922\xf26\xec\xb6\xed\x8b\xc3U\x13\x9d\xc5\x170\xa4\xfa^\x92\xacDF\x8a\x97\xd6\x19\xfe\xdd\xb8\xbd\x1a\x9a\x19\xa3\x80ankR\x8b\xe5\xd83]\xa9\xc6\x08\x82f\xf6\xb9"6l$\xb8j@\xc0\x8a\xb0l1..\xbak\x83ls\x15\xbc\xf4\xc1\x13\xbe\xf8E\xb8\x9d\r\xa8\x9dk\x84\xd3n\xfa\xacQ\x07\xb1%y\xaav\xb4\x08\xe0z\x1b\x16\xf5\x04\xe9\xcc\xb9\x08z\x1en7.G\xfc]\xc9\x14\xe1B@\xbb!8`' def decompress(data): - import popen2 + if os.name != "nt": + import popen2 + pop = popen2.Popen3("bunzip2", capturestderr=1) + pop.tochild.write(data) + pop.tochild.close() + res = pop.fromchild.read() + pop.fromchild.close() + if pop.wait() == 0: + return res + import bz2 - pop = popen2.Popen3("bunzip2", capturestderr=1) - pop.tochild.write(data) - pop.tochild.close() - res = pop.fromchild.read() - pop.fromchild.close() - if pop.wait() != 0: - res = bz2.decompress(data) - return res + return bz2.decompress(data) mod.TEXT = 'root:x:0:0:root:/root:/bin/bash\nbin:x:1:1:bin:/bin:\ndaemon:x:2:2:daemon:/sbin:\nadm:x:3:4:adm:/var/adm:\nlp:x:4:7:lp:/var/spool/lpd:\nsync:x:5:0:sync:/sbin:/bin/sync\nshutdown:x:6:0:shutdown:/sbin:/sbin/shutdown\nhalt:x:7:0:halt:/sbin:/sbin/halt\nmail:x:8:12:mail:/var/spool/mail:\nnews:x:9:13:news:/var/spool/news:\nuucp:x:10:14:uucp:/var/spool/uucp:\noperator:x:11:0:operator:/root:\ngames:x:12:100:games:/usr/games:\ngopher:x:13:30:gopher:/usr/lib/gopher-data:\nftp:x:14:50:FTP User:/var/ftp:/bin/bash\nnobody:x:65534:65534:Nobody:/home:\npostfix:x:100:101:postfix:/var/spool/postfix:\nniemeyer:x:500:500::/home/niemeyer:/bin/bash\npostgres:x:101:102:PostgreSQL Server:/var/lib/pgsql:/bin/bash\nmysql:x:102:103:MySQL server:/var/lib/mysql:/bin/bash\nwww:x:103:104::/var/www:/bin/false\n' mod.DATA = DATA Modified: pypy/branch/build-external/pypy/module/bz2/test/test_bz2_file.py ============================================================================== --- pypy/branch/build-external/pypy/module/bz2/test/test_bz2_file.py (original) +++ pypy/branch/build-external/pypy/module/bz2/test/test_bz2_file.py Wed May 28 16:21:42 2008 @@ -3,10 +3,6 @@ from pypy.module.bz2.test.support import CheckAllocation import os -if os.name == "nt": - from py.test import skip - skip("bz2 module is not available on Windows") - def setup_module(mod): DATA = 'BZh91AY&SY.\xc8N\x18\x00\x01>_\x80\x00\x10@\x02\xff\xf0\x01\x07n\x00?\xe7\xff\xe00\x01\x99\xaa\x00\xc0\x03F\x86\x8c#&\x83F\x9a\x03\x06\xa6\xd0\xa6\x93M\x0fQ\xa7\xa8\x06\x804hh\x12$\x11\xa4i4\xf14S\xd2\x88\xe5\xcd9gd6\x0b\n\xe9\x9b\xd5\x8a\x99\xf7\x08.K\x8ev\xfb\xf7xw\xbb\xdf\xa1\x92\xf1\xdd|/";\xa2\xba\x9f\xd5\xb1#A\xb6\xf6\xb3o\xc9\xc5y\\\xebO\xe7\x85\x9a\xbc\xb6f8\x952\xd5\xd7"%\x89>V,\xf7\xa6z\xe2\x9f\xa3\xdf\x11\x11"\xd6E)I\xa9\x13^\xca\xf3r\xd0\x03U\x922\xf26\xec\xb6\xed\x8b\xc3U\x13\x9d\xc5\x170\xa4\xfa^\x92\xacDF\x8a\x97\xd6\x19\xfe\xdd\xb8\xbd\x1a\x9a\x19\xa3\x80ankR\x8b\xe5\xd83]\xa9\xc6\x08\x82f\xf6\xb9"6l$\xb8j@\xc0\x8a\xb0l1..\xbak\x83ls\x15\xbc\xf4\xc1\x13\xbe\xf8E\xb8\x9d\r\xa8\x9dk\x84\xd3n\xfa\xacQ\x07\xb1%y\xaav\xb4\x08\xe0z\x1b\x16\xf5\x04\xe9\xcc\xb9\x08z\x1en7.G\xfc]\xc9\x14\xe1B@\xbb!8`' DATA_CRLF = 'BZh91AY&SY\xaez\xbbN\x00\x01H\xdf\x80\x00\x12@\x02\xff\xf0\x01\x07n\x00?\xe7\xff\xe0@\x01\xbc\xc6`\x86*\x8d=M\xa9\x9a\x86\xd0L@\x0fI\xa6!\xa1\x13\xc8\x88jdi\x8d@\x03@\x1a\x1a\x0c\x0c\x83 \x00\xc4h2\x19\x01\x82D\x84e\t\xe8\x99\x89\x19\x1ah\x00\r\x1a\x11\xaf\x9b\x0fG\xf5(\x1b\x1f?\t\x12\xcf\xb5\xfc\x95E\x00ps\x89\x12^\xa4\xdd\xa2&\x05(\x87\x04\x98\x89u\xe40%\xb6\x19\'\x8c\xc4\x89\xca\x07\x0e\x1b!\x91UIFU%C\x994!DI\xd2\xfa\xf0\xf1N8W\xde\x13A\xf5\x9cr%?\x9f3;I45A\xd1\x8bT\xb1\xa4\xc7\x8d\x1a\\"\xad\xa1\xabyBg\x15\xb9l\x88\x88\x91k"\x94\xa4\xd4\x89\xae*\xa6\x0b\x10\x0c\xd6\xd4m\xe86\xec\xb5j\x8a\x86j\';\xca.\x01I\xf2\xaaJ\xe8\x88\x8cU+t3\xfb\x0c\n\xa33\x13r2\r\x16\xe0\xb3(\xbf\x1d\x83r\xe7M\xf0D\x1365\xd8\x88\xd3\xa4\x92\xcb2\x06\x04\\\xc1\xb0\xea//\xbek&\xd8\xe6+t\xe5\xa1\x13\xada\x16\xder5"w]\xa2i\xb7[\x97R \xe2IT\xcd;Z\x04dk4\xad\x8a\t\xd3\x81z\x10\xf1:^`\xab\x1f\xc5\xdc\x91N\x14$+\x9e\xae\xd3\x80' @@ -18,16 +14,18 @@ f.write(data) def decompress(data): - import popen2 + if os.name != "nt": + import popen2 + pop = popen2.Popen3("bunzip2", capturestderr=1) + pop.tochild.write(data) + pop.tochild.close() + res = pop.fromchild.read() + pop.fromchild.close() + if pop.wait() == 0: + return res + import bz2 - pop = popen2.Popen3("bunzip2", capturestderr=1) - pop.tochild.write(data) - pop.tochild.close() - res = pop.fromchild.read() - pop.fromchild.close() - if pop.wait() != 0: - res = bz2.decompress(data) - return res + return bz2.decompress(data) mod.TEXT = 'root:x:0:0:root:/root:/bin/bash\nbin:x:1:1:bin:/bin:\ndaemon:x:2:2:daemon:/sbin:\nadm:x:3:4:adm:/var/adm:\nlp:x:4:7:lp:/var/spool/lpd:\nsync:x:5:0:sync:/sbin:/bin/sync\nshutdown:x:6:0:shutdown:/sbin:/sbin/shutdown\nhalt:x:7:0:halt:/sbin:/sbin/halt\nmail:x:8:12:mail:/var/spool/mail:\nnews:x:9:13:news:/var/spool/news:\nuucp:x:10:14:uucp:/var/spool/uucp:\noperator:x:11:0:operator:/root:\ngames:x:12:100:games:/usr/games:\ngopher:x:13:30:gopher:/usr/lib/gopher-data:\nftp:x:14:50:FTP User:/var/ftp:/bin/bash\nnobody:x:65534:65534:Nobody:/home:\npostfix:x:100:101:postfix:/var/spool/postfix:\nniemeyer:x:500:500::/home/niemeyer:/bin/bash\npostgres:x:101:102:PostgreSQL Server:/var/lib/pgsql:/bin/bash\nmysql:x:102:103:MySQL server:/var/lib/mysql:/bin/bash\nwww:x:103:104::/var/www:/bin/false\n' mod.DATA = DATA From fijal at codespeak.net Wed May 28 16:52:07 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 28 May 2008 16:52:07 +0200 (CEST) Subject: [pypy-svn] r55353 - pypy/dist/pypy/module/_rawffi Message-ID: <20080528145207.38B9B16857C@codespeak.net> Author: fijal Date: Wed May 28 16:52:06 2008 New Revision: 55353 Modified: pypy/dist/pypy/module/_rawffi/callback.py Log: typo, thanks amaury Modified: pypy/dist/pypy/module/_rawffi/callback.py ============================================================================== --- pypy/dist/pypy/module/_rawffi/callback.py (original) +++ pypy/dist/pypy/module/_rawffi/callback.py Wed May 28 16:52:06 2008 @@ -33,7 +33,7 @@ w_args = space.newlist([space.wrap(rffi.cast(rffi.UINT, ll_args[i])) for i in range(len(argtypes))]) w_res = space.call(w_callable, w_args) - if callback_ptr.res != 'O': # don't return void + if callback_ptr.result != 'O': # don't return void unwrap_value(space, push_elem, ll_res, 0, letter2tp(space, callback_ptr.result), w_res) except OperationError, e: From fijal at codespeak.net Wed May 28 17:08:24 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 28 May 2008 17:08:24 +0200 (CEST) Subject: [pypy-svn] r55356 - pypy/dist/pypy/module/_rawffi/test Message-ID: <20080528150824.660A4698071@codespeak.net> Author: fijal Date: Wed May 28 17:08:20 2008 New Revision: 55356 Modified: pypy/dist/pypy/module/_rawffi/test/test__rawffi.py Log: Fix the test Modified: pypy/dist/pypy/module/_rawffi/test/test__rawffi.py ============================================================================== --- pypy/dist/pypy/module/_rawffi/test/test__rawffi.py (original) +++ pypy/dist/pypy/module/_rawffi/test/test__rawffi.py Wed May 28 17:08:20 2008 @@ -465,13 +465,12 @@ def compare(a, b): a1 = _rawffi.Array('i').fromaddress(_rawffi.Array('i').fromaddress(a, 1)[0], 1) a2 = _rawffi.Array('i').fromaddress(_rawffi.Array('i').fromaddress(b, 1)[0], 1) + print "comparing", a1[0], "with", a2[0] if a1[0] not in [1,2,3,4] or a2[0] not in [1,2,3,4]: - print "comparing", a1[0], "with", a2[0] bogus_args = True if a1[0] > a2[0]: - res = -1 - res = 1 - return res + return 1 + return -1 a1 = ll_to_sort.byptr() a2 = _rawffi.Array('i')(1) a2[0] = len(ll_to_sort) From arigo at codespeak.net Wed May 28 17:10:39 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 28 May 2008 17:10:39 +0200 (CEST) Subject: [pypy-svn] r55357 - pypy/dist/pypy/module/_rawffi/test Message-ID: <20080528151039.E9BFB698036@codespeak.net> Author: arigo Date: Wed May 28 17:10:39 2008 New Revision: 55357 Modified: pypy/dist/pypy/module/_rawffi/test/test__rawffi.py Log: Fix bogus_args (it had no effect in the previous version). Modified: pypy/dist/pypy/module/_rawffi/test/test__rawffi.py ============================================================================== --- pypy/dist/pypy/module/_rawffi/test/test__rawffi.py (original) +++ pypy/dist/pypy/module/_rawffi/test/test__rawffi.py Wed May 28 17:10:39 2008 @@ -461,13 +461,13 @@ ll_to_sort[i] = 4-i qsort = libc.ptr('qsort', ['P', 'i', 'i', 'P'], None) resarray = _rawffi.Array('i')(1) - bogus_args = False + bogus_args = [] def compare(a, b): a1 = _rawffi.Array('i').fromaddress(_rawffi.Array('i').fromaddress(a, 1)[0], 1) a2 = _rawffi.Array('i').fromaddress(_rawffi.Array('i').fromaddress(b, 1)[0], 1) print "comparing", a1[0], "with", a2[0] if a1[0] not in [1,2,3,4] or a2[0] not in [1,2,3,4]: - bogus_args = True + bogus_args.append((a1[0], a2[0])) if a1[0] > a2[0]: return 1 return -1 From arigo at codespeak.net Wed May 28 17:26:38 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 28 May 2008 17:26:38 +0200 (CEST) Subject: [pypy-svn] r55358 - pypy/dist/pypy/doc Message-ID: <20080528152638.EC1C8169EB0@codespeak.net> Author: arigo Date: Wed May 28 17:26:36 2008 New Revision: 55358 Modified: pypy/dist/pypy/doc/cpython_differences.txt Log: Expand the two paragraphs (in each case, the behavior difference is a bit more general than these very specific examples). Modified: pypy/dist/pypy/doc/cpython_differences.txt ============================================================================== --- pypy/dist/pypy/doc/cpython_differences.txt (original) +++ pypy/dist/pypy/doc/cpython_differences.txt Wed May 28 17:26:36 2008 @@ -16,16 +16,26 @@ XXX: write me please -Subclasses of builtin ``dict`` objects --------------------------------------- +Subclasses of built-in types +---------------------------- -When you pass an instance of a subclass of ``dict`` to the -``dict.update`` method, CPython simply ignores potentially overridden -methods, such as ``keys()`` or ``__getitem__()``; on the other hand, -PyPy correctly calls the overridden versions of the methods. - -For example, the following code prints ``42`` on PyPy but ``foo`` -on CPython:: +Officially, CPython has no rule at all for when exactly +overriden method of subclasses of built-in types get +implicitly called or not. As an approximation, these methods +are never called by other built-in methods of the same object. +For example, an overridden ``__getitem__()`` in a subclass of +``dict`` will not be called by e.g. the built-in ``get()`` +method. + +The above is true both in CPython and in PyPy. Differences +can occur about whether a built-in function or method will +call an overridden method of *another* object than ``self``. +In PyPy, they are generally always called, whereas not in +CPython. For example, in PyPy, ``dict1.update(dict2)`` +considers that ``dict2`` is just a general mapping object, and +will thus call overridden ``keys()`` and ``__getitem__()`` +methods on it. So the following code prints ``42`` on PyPy +but ``foo`` on CPython:: >>>> class D(dict): .... def __getitem__(self, key): @@ -38,10 +48,18 @@ >>>> print d1['a'] 42 -Comparison differencies + +Ignored exceptions ----------------------- -When custom \_\_eq\_\_ function on object (or any other rich comparison -method) raises an exception, we don't swallow the exception and instead -report it to user. +In many corner cases, CPython can silently swallow exceptions. +The precise list of when this occurs is rather long, even +though most cases are very uncommon. The most well-known +places are custom rich comparison methods (like \_\_eq\_\_); +dictionary lookup; calls to some built-in functions like +isinstance(). + +Unless this behavior is clearly present by design and +documented as such (as e.g. for hasattr()), in most cases PyPy +lets the exception propagate instead. From arigo at codespeak.net Wed May 28 17:54:48 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 28 May 2008 17:54:48 +0200 (CEST) Subject: [pypy-svn] r55359 - pypy/dist/pypy/doc Message-ID: <20080528155448.C6A8B169EF2@codespeak.net> Author: arigo Date: Wed May 28 17:54:46 2008 New Revision: 55359 Modified: pypy/dist/pypy/doc/cpython_differences.txt Log: Wrote "Differences related to garbage collection strategies" Modified: pypy/dist/pypy/doc/cpython_differences.txt ============================================================================== --- pypy/dist/pypy/doc/cpython_differences.txt (original) +++ pypy/dist/pypy/doc/cpython_differences.txt Wed May 28 17:54:46 2008 @@ -13,7 +13,36 @@ Differences related to garbage collection strategies ---------------------------------------------------- -XXX: write me please +PyPy's garbage collector is not based on reference counting, so the +objects are not freed instantly when they are no longer reachable. The +most obvious effect of this is that files are not promptly closed when +they go out of scope. For files that are opened for writing, data can +be left sitting in their output buffers for a while, making the on-disk +file appear empty or truncated. + +Fixing this is essentially not possible without forcing a +reference-counting approach to garbage collection. The effect that you +get in CPython has clearly been described as a side-effect of the +implementation and not a language design decision: programs relying on +this are basically bogus. It would anyway be insane to try to enforce +CPython's behavior in a language spec, given that it has no chance to be +adopted by Jython or IronPython (or any other port of Python to Java or +.NET, like PyPy itself). + +There are a few extra implications for the difference in the GC. Most +notably, if an object has a __del__, the __del__ is never called more +than once in PyPy; but CPython will call the same __del__ several times +if the object is resurrected and dies again. + +The built-in function ``id()`` returns numbers that are not addresses. +This is most visible in the default repr: a typical PyPy object can +pretend to be located ``at 0x00000009``. This is just its ``id()``, not +its real address (because the physical address can change). + +Note that if you have a long chain of objects, each with a reference to +the next one, and each with a __del__, PyPy's GC will perform badly. On +the bright side, in most other cases, benchmarks have shown that PyPy's +GCs perform much better than CPython's. Subclasses of built-in types From xoraxax at codespeak.net Wed May 28 18:16:45 2008 From: xoraxax at codespeak.net (xoraxax at codespeak.net) Date: Wed, 28 May 2008 18:16:45 +0200 (CEST) Subject: [pypy-svn] r55360 - pypy/dist/pypy/doc Message-ID: <20080528161645.5B511169E17@codespeak.net> Author: xoraxax Date: Wed May 28 18:16:44 2008 New Revision: 55360 Modified: pypy/dist/pypy/doc/cpython_differences.txt Log: Make it a bit more obvious that pypy is full of garbage collectors. Modified: pypy/dist/pypy/doc/cpython_differences.txt ============================================================================== --- pypy/dist/pypy/doc/cpython_differences.txt (original) +++ pypy/dist/pypy/doc/cpython_differences.txt Wed May 28 18:16:44 2008 @@ -13,12 +13,12 @@ Differences related to garbage collection strategies ---------------------------------------------------- -PyPy's garbage collector is not based on reference counting, so the -objects are not freed instantly when they are no longer reachable. The -most obvious effect of this is that files are not promptly closed when -they go out of scope. For files that are opened for writing, data can -be left sitting in their output buffers for a while, making the on-disk -file appear empty or truncated. +Most of the garbage collectors used or implemented by PyPy are not based on +reference counting, so the objects are not freed instantly when they are no +longer reachable. The most obvious effect of this is that files are not +promptly closed when they go out of scope. For files that are opened for +writing, data can be left sitting in their output buffers for a while, making +the on-disk file appear empty or truncated. Fixing this is essentially not possible without forcing a reference-counting approach to garbage collection. The effect that you @@ -34,7 +34,8 @@ than once in PyPy; but CPython will call the same __del__ several times if the object is resurrected and dies again. -The built-in function ``id()`` returns numbers that are not addresses. +The built-in function ``id()`` returns numbers that are not addresses +for most of PyPy's garbage collectors. This is most visible in the default repr: a typical PyPy object can pretend to be located ``at 0x00000009``. This is just its ``id()``, not its real address (because the physical address can change). From fijal at codespeak.net Wed May 28 18:55:45 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 28 May 2008 18:55:45 +0200 (CEST) Subject: [pypy-svn] r55361 - pypy/dist/pypy/lib/app_test Message-ID: <20080528165545.31A2C169F32@codespeak.net> Author: fijal Date: Wed May 28 18:55:42 2008 New Revision: 55361 Modified: pypy/dist/pypy/lib/app_test/test_pyexpat.py Log: Fix test to run correctly even without random symlinks. Skip tests which fail on cpy 2.5 Modified: pypy/dist/pypy/lib/app_test/test_pyexpat.py ============================================================================== --- pypy/dist/pypy/lib/app_test/test_pyexpat.py (original) +++ pypy/dist/pypy/lib/app_test/test_pyexpat.py Wed May 28 18:55:42 2008 @@ -2,10 +2,11 @@ # handler, are obscure and unhelpful. import StringIO, sys -import unittest +import unittest, py import pyexpat -from xml.parsers import expat +#from xml.parsers import expat +expat = pyexpat from test.test_support import sortdict, run_unittest @@ -254,6 +255,7 @@ class TestInterning: def test(self): + py.test.skip("Not working") # Test the interning machinery. p = expat.ParserCreate() L = [] @@ -310,8 +312,7 @@ # Make sure buffering is turned on assert self.parser.buffer_text self.parser.Parse("123", 1) - assert self.stuff == ['123'], ( - "buffered text not properly collapsed") + assert self.stuff == ['123'] def test1(self): # XXX This test exposes more detail of Expat's text chunking than we @@ -370,6 +371,7 @@ raise RuntimeError(name) def test(self): + py.test.skip("not implemented") parser = expat.ParserCreate() parser.StartElementHandler = self.StartElementHandler try: @@ -442,7 +444,10 @@ """ def setup_class(cls): import py - py.test.skip("Doesn't work on cpy 2.5") + try: + import __pypy__ + except ImportError: + py.test.skip("Doesn't work on cpy 2.5") def test_1025_bytes(self): assert self.small_buffer_test(1025) == 2 From arigo at codespeak.net Wed May 28 19:19:10 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 28 May 2008 19:19:10 +0200 (CEST) Subject: [pypy-svn] r55362 - pypy/branch/gc+thread/pypy/config Message-ID: <20080528171910.E9F2F169F32@codespeak.net> Author: arigo Date: Wed May 28 19:19:09 2008 New Revision: 55362 Modified: pypy/branch/gc+thread/pypy/config/translationoption.py Log: Threads only work with the regular shadowstack gcrootfinder. Modified: pypy/branch/gc+thread/pypy/config/translationoption.py ============================================================================== --- pypy/branch/gc+thread/pypy/config/translationoption.py (original) +++ pypy/branch/gc+thread/pypy/config/translationoption.py Wed May 28 19:19:09 2008 @@ -71,9 +71,11 @@ requires={ "shadowstack": [("translation.gctransformer", "framework")], "llvmgc": [("translation.gctransformer", "framework"), - ("translation.backend", "llvm")], + ("translation.backend", "llvm"), + ("translation.thread", False)], "asmgcc": [("translation.gctransformer", "framework"), - ("translation.backend", "c")], + ("translation.backend", "c"), + ("translation.thread", False)], }, suggests={ "shadowstack": [("translation.gc", "generation")], From arigo at codespeak.net Wed May 28 19:21:13 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 28 May 2008 19:21:13 +0200 (CEST) Subject: [pypy-svn] r55363 - in pypy/dist/pypy: module/_file module/sys rlib translator/goal/test2 Message-ID: <20080528172113.28174169F32@codespeak.net> Author: arigo Date: Wed May 28 19:21:11 2008 New Revision: 55363 Modified: pypy/dist/pypy/module/_file/interp_file.py pypy/dist/pypy/module/sys/state.py pypy/dist/pypy/rlib/streamio.py pypy/dist/pypy/translator/goal/test2/test_app_main.py Log: issue372 in-progress This should ensure that reading from stdin always flushes stdout first. Modified: pypy/dist/pypy/module/_file/interp_file.py ============================================================================== --- pypy/dist/pypy/module/_file/interp_file.py (original) +++ pypy/dist/pypy/module/_file/interp_file.py Wed May 28 19:21:11 2008 @@ -63,6 +63,16 @@ space.wrap('I/O operation on closed file')) return stream + def _when_reading_first_flush(self, otherfile): + """Flush otherfile before reading from self.""" + self.stream = streamio.CallbackReadFilter(self.stream, + otherfile._try_to_flush) + + def _try_to_flush(self): + stream = self.stream + if stream is not None: + stream.flush() + # ____________________________________________________________ # # The 'direct_' methods assume that the caller already acquired the Modified: pypy/dist/pypy/module/sys/state.py ============================================================================== --- pypy/dist/pypy/module/sys/state.py (original) +++ pypy/dist/pypy/module/sys/state.py Wed May 28 19:21:11 2008 @@ -94,6 +94,8 @@ stderr.name = '' self.w_stderr = space.wrap(stderr) + stdin._when_reading_first_flush(stdout) + def getio(space): return space.fromcache(IOState) Modified: pypy/dist/pypy/rlib/streamio.py ============================================================================== --- pypy/dist/pypy/rlib/streamio.py (original) +++ pypy/dist/pypy/rlib/streamio.py Wed May 28 19:21:11 2008 @@ -944,6 +944,32 @@ flush_buffers=False) +class CallbackReadFilter(Stream): + """Pseudo read filter that invokes a callback before blocking on a read. + """ + + def __init__(self, base, callback): + self.base = base + self.callback = callback + + def flush_buffers(self): + self.callback() + + tell = PassThrough("tell", flush_buffers=False) + seek = PassThrough("seek", flush_buffers=False) + read = PassThrough("read", flush_buffers=True) + readall = PassThrough("readall", flush_buffers=True) + readline = PassThrough("readline", flush_buffers=True) + peek = PassThrough("peek", flush_buffers=False) + flush = PassThrough("flush", flush_buffers=False) + flushable = PassThrough("flushable", flush_buffers=False) + close = PassThrough("close", flush_buffers=False) + write = PassThrough("write", flush_buffers=False) + truncate = PassThrough("truncate", flush_buffers=False) + getnewlines= PassThrough("getnewlines",flush_buffers=False) + try_to_find_file_descriptor = PassThrough("try_to_find_file_descriptor", + flush_buffers=False) + # _________________________________________________ # The following functions are _not_ RPython! Modified: pypy/dist/pypy/translator/goal/test2/test_app_main.py ============================================================================== --- pypy/dist/pypy/translator/goal/test2/test_app_main.py (original) +++ pypy/dist/pypy/translator/goal/test2/test_app_main.py Wed May 28 19:21:11 2008 @@ -312,6 +312,22 @@ finally: os.environ['PYTHONINSPECT'] = old + def test_stdout_flushes_before_stdin_blocks(self): + # This doesn't really test app_main.py, but a behavior that + # can only be checked on top of py.py with pexpect. + path = getscript(""" + import sys + sys.stdout.write('Are you suggesting coconuts migrate? ') + line = sys.stdin.readline() + assert line.rstrip() == 'Not at all. They could be carried.' + print 'A five ounce bird could not carry a one pound coconut.' + """) + py_py = os.path.join(autopath.pypydir, 'bin', 'py.py') + child = self._spawn(sys.executable, [py_py, path]) + child.expect('Are you suggesting coconuts migrate?', timeout=120) + child.sendline('Not at all. They could be carried.') + child.expect('A five ounce bird could not carry a one pound coconut.') + class TestNonInteractive: From arigo at codespeak.net Wed May 28 19:45:18 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 28 May 2008 19:45:18 +0200 (CEST) Subject: [pypy-svn] r55365 - in pypy/branch/gc+thread/pypy/rpython: . lltypesystem lltypesystem/test Message-ID: <20080528174518.99F1D169F48@codespeak.net> Author: arigo Date: Wed May 28 19:45:15 2008 New Revision: 55365 Modified: pypy/branch/gc+thread/pypy/rpython/llinterp.py pypy/branch/gc+thread/pypy/rpython/lltypesystem/llheap.py pypy/branch/gc+thread/pypy/rpython/lltypesystem/rffi.py pypy/branch/gc+thread/pypy/rpython/lltypesystem/test/test_rffi.py Log: Mostly fixes for tests. Modified: pypy/branch/gc+thread/pypy/rpython/llinterp.py ============================================================================== --- pypy/branch/gc+thread/pypy/rpython/llinterp.py (original) +++ pypy/branch/gc+thread/pypy/rpython/llinterp.py Wed May 28 19:45:15 2008 @@ -774,6 +774,9 @@ addr = llmemory.cast_ptr_to_adr(ptr) return self.heap.can_move(addr) + def op_gc_thread_prepare(self): + self.heap.thread_prepare() + def op_gc_thread_run(self): self.heap.thread_run() Modified: pypy/branch/gc+thread/pypy/rpython/lltypesystem/llheap.py ============================================================================== --- pypy/branch/gc+thread/pypy/rpython/lltypesystem/llheap.py (original) +++ pypy/branch/gc+thread/pypy/rpython/lltypesystem/llheap.py Wed May 28 19:45:15 2008 @@ -35,6 +35,9 @@ ll_str.chars[i] = buf.chars[i] return ll_str +def thread_prepare(): + pass + def thread_run(): pass Modified: pypy/branch/gc+thread/pypy/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/branch/gc+thread/pypy/rpython/lltypesystem/rffi.py (original) +++ pypy/branch/gc+thread/pypy/rpython/lltypesystem/rffi.py Wed May 28 19:45:15 2008 @@ -163,9 +163,12 @@ return cast(lltype.Unsigned, res) return res wrapper._annspecialcase_ = 'specialize:ll' - # don't inline, as a hack to guarantee that no GC pointer is alive - # in the final part of the wrapper - wrapper._dont_inline_ = True + if invoke_around_handlers: + # don't inline, as a hack to guarantee that no GC pointer is alive + # in the final part of the wrapper + wrapper._dont_inline_ = True + else: + wrapper._always_inline_ = True # for debugging, stick ll func ptr to that wrapper._ptr = funcptr Modified: pypy/branch/gc+thread/pypy/rpython/lltypesystem/test/test_rffi.py ============================================================================== --- pypy/branch/gc+thread/pypy/rpython/lltypesystem/test/test_rffi.py (original) +++ pypy/branch/gc+thread/pypy/rpython/lltypesystem/test/test_rffi.py Wed May 28 19:45:15 2008 @@ -531,7 +531,8 @@ assert interpret(f, []) == 3 def test_implicit_cast(self): - z = llexternal('z', [USHORT, ULONG, USHORT, DOUBLE], USHORT) + z = llexternal('z', [USHORT, ULONG, USHORT, DOUBLE], USHORT, + sandboxsafe=True) # to allow the wrapper to be inlined def f(x, y, xx, yy): return z(x, y, xx, yy) From arigo at codespeak.net Wed May 28 19:48:58 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 28 May 2008 19:48:58 +0200 (CEST) Subject: [pypy-svn] r55366 - in pypy/dist/pypy: config interpreter module/thread module/thread/test rlib rpython rpython/lltypesystem rpython/lltypesystem/test rpython/memory rpython/memory/gctransform translator/c translator/c/src translator/c/test Message-ID: <20080528174858.AAEF4169F48@codespeak.net> Author: arigo Date: Wed May 28 19:48:56 2008 New Revision: 55366 Added: pypy/dist/pypy/module/thread/test/test_gil.py (contents, props changed) Modified: pypy/dist/pypy/config/translationoption.py pypy/dist/pypy/interpreter/miscutils.py pypy/dist/pypy/module/thread/gil.py pypy/dist/pypy/module/thread/ll_thread.py pypy/dist/pypy/module/thread/os_thread.py pypy/dist/pypy/module/thread/test/support.py pypy/dist/pypy/module/thread/test/test_ll_thread.py pypy/dist/pypy/module/thread/threadlocals.py pypy/dist/pypy/rlib/rposix.py pypy/dist/pypy/rpython/llinterp.py pypy/dist/pypy/rpython/lltypesystem/llheap.py pypy/dist/pypy/rpython/lltypesystem/lloperation.py pypy/dist/pypy/rpython/lltypesystem/rffi.py pypy/dist/pypy/rpython/lltypesystem/test/test_rffi.py pypy/dist/pypy/rpython/memory/gctransform/framework.py pypy/dist/pypy/rpython/memory/support.py pypy/dist/pypy/translator/c/gc.py pypy/dist/pypy/translator/c/src/thread.h pypy/dist/pypy/translator/c/src/thread_nt.h pypy/dist/pypy/translator/c/src/thread_pthread.h pypy/dist/pypy/translator/c/test/test_boehm.py Log: Make PyPy threads compatible with the framework GCs. (svn merge -r55299:55365 svn+ssh://codespeak.net/svn/pypy/branch/gc+thread) The approach is to create one shadow stack for each thread. Done by adding three ad-hoc operations that the gctransformer knows about, gc_thread_*(). This is all a bit fragile, sadly. pypy/module/thread/os_thread is a bit simplified by replacing the hack of the raw-malloced Bootstrap instances with a single prebuilt global Bootstrap instance, and a lock to protect it as needed. This should remove all GC-specific issues that where related to this strange instance. pypy/module/thread uses rffi even more directly now, relying on the exact details of the GIL-releasing logic that rffi can put in external function calls and in callbacks. Modified: pypy/dist/pypy/config/translationoption.py ============================================================================== --- pypy/dist/pypy/config/translationoption.py (original) +++ pypy/dist/pypy/config/translationoption.py Wed May 28 19:48:56 2008 @@ -71,9 +71,11 @@ requires={ "shadowstack": [("translation.gctransformer", "framework")], "llvmgc": [("translation.gctransformer", "framework"), - ("translation.backend", "llvm")], + ("translation.backend", "llvm"), + ("translation.thread", False)], "asmgcc": [("translation.gctransformer", "framework"), - ("translation.backend", "c")], + ("translation.backend", "c"), + ("translation.thread", False)], }, suggests={ "shadowstack": [("translation.gc", "generation")], @@ -81,8 +83,7 @@ "asmgcc": [("translation.gc", "generation")], }), BoolOption("thread", "enable use of threading primitives", - default=False, cmdline="--thread", - requires=[("translation.gc", "boehm")]), + default=False, cmdline="--thread"), BoolOption("verbose", "Print extra information", default=False), BoolOption("debug", "Record extra annotation information", cmdline="-d --debug", default=False), Modified: pypy/dist/pypy/interpreter/miscutils.py ============================================================================== --- pypy/dist/pypy/interpreter/miscutils.py (original) +++ pypy/dist/pypy/interpreter/miscutils.py Wed May 28 19:48:56 2008 @@ -168,9 +168,6 @@ def getmainthreadvalue(self): return self._value - def getGIL(self): - return None # XXX temporary hack! - class Action(object): """Abstract base class for actions that must be performed regularly, Modified: pypy/dist/pypy/module/thread/gil.py ============================================================================== --- pypy/dist/pypy/module/thread/gil.py (original) +++ pypy/dist/pypy/module/thread/gil.py Wed May 28 19:48:56 2008 @@ -5,7 +5,7 @@ # This module adds a global lock to an object space. # If multiple threads try to execute simultaneously in this space, # all but one will be blocked. The other threads get a chance to run -# from time to time, using the executioncontext's XXX +# from time to time, using the hook yield_thread(). from pypy.module.thread import ll_thread as thread from pypy.module.thread.error import wrap_thread_error @@ -16,15 +16,16 @@ class GILThreadLocals(OSThreadLocals): """A version of OSThreadLocals that enforces a GIL.""" - GIL = None + ll_GIL = thread.null_ll_lock def setup_threads(self, space): """Enable threads in the object space, if they haven't already been.""" - if self.GIL is None: + if not self.ll_GIL: try: - self.GIL = thread.allocate_lock_NOAUTO() + self.ll_GIL = thread.allocate_ll_lock() except thread.error: raise wrap_thread_error(space, "can't allocate GIL") + thread.acquire_NOAUTO(self.ll_GIL, True) self.enter_thread(space) # setup the main thread # add the GIL-releasing callback as an action on the space space.pending_actions.append(GILReleaseAction(self)) @@ -40,31 +41,17 @@ # test_lock_again after the global state was cleared by # test_compile_lock. As a workaround, we repatch these global # fields systematically. - spacestate.GIL = self.GIL + spacestate.ll_GIL = self.ll_GIL invoke_around_extcall(before_external_call, after_external_call) return result - def enter_thread(self, space): - "Notification that the current thread is just starting: grab the GIL." - self.GIL.acquire(True) - OSThreadLocals.enter_thread(self, space) - - def leave_thread(self, space): - "Notification that the current thread is stopping: release the GIL." - OSThreadLocals.leave_thread(self, space) - self.GIL.release() - def yield_thread(self): """Notification that the current thread is between two bytecodes: release the GIL for a little while.""" - GIL = self.GIL - # Other threads can run between the release() and the acquire(). - # This is a single external function so that we are sure that nothing - # occurs between the release and the acquire, e.g. no GC operation. - GIL.fused_release_acquire() - - def getGIL(self): - return self.GIL # XXX temporary hack! + # Other threads can run between the release() and the acquire() + # implicit in the following external function call (which has + # otherwise no effect). + thread.yield_thread() class GILReleaseAction(Action): @@ -81,7 +68,9 @@ class SpaceState: - pass + def _freeze_(self): + self.ll_GIL = thread.null_ll_lock + return False spacestate = SpaceState() # Fragile code below. We have to preserve the C-level errno manually... @@ -90,10 +79,13 @@ # this function must not raise, in such a way that the exception # transformer knows that it cannot raise! e = get_errno() - spacestate.GIL.release() + thread.release_NOAUTO(spacestate.ll_GIL) set_errno(e) +before_external_call._gctransformer_hint_cannot_collect_ = True def after_external_call(): e = get_errno() - spacestate.GIL.acquire(True) + thread.acquire_NOAUTO(spacestate.ll_GIL, True) + thread.gc_thread_run() set_errno(e) +after_external_call._gctransformer_hint_cannot_collect_ = True Modified: pypy/dist/pypy/module/thread/ll_thread.py ============================================================================== --- pypy/dist/pypy/module/thread/ll_thread.py (original) +++ pypy/dist/pypy/module/thread/ll_thread.py Wed May 28 19:48:56 2008 @@ -6,16 +6,19 @@ from pypy.rpython.annlowlevel import cast_instance_to_base_ptr from pypy.translator.tool.cbuild import ExternalCompilationInfo from pypy.rpython.lltypesystem import llmemory -import thread, py, os +import py, os from pypy.rpython.extregistry import ExtRegistryEntry from pypy.annotation import model as annmodel from pypy.rpython.lltypesystem.lltype import typeOf from pypy.rlib.debug import ll_assert +from pypy.rlib.objectmodel import we_are_translated +from pypy.rpython.lltypesystem.lloperation import llop from pypy.tool import autopath from distutils import sysconfig python_inc = sysconfig.get_python_inc() -error = thread.error +class error(Exception): + pass eci = ExternalCompilationInfo( includes = ['src/thread.h'], @@ -24,102 +27,75 @@ python_inc], export_symbols = ['RPyThreadGetIdent', 'RPyThreadLockInit', 'RPyThreadAcquireLock', 'RPyThreadReleaseLock', - 'RPyThreadFusedReleaseAcquireLock',] + 'RPyThreadYield'] ) def llexternal(name, args, result, **kwds): + kwds.setdefault('sandboxsafe', True) return rffi.llexternal(name, args, result, compilation_info=eci, **kwds) -CALLBACK = lltype.Ptr(lltype.FuncType([rffi.VOIDP], rffi.VOIDP)) -c_thread_start = llexternal('RPyThreadStart', [CALLBACK, rffi.VOIDP], rffi.INT) -c_thread_get_ident = llexternal('RPyThreadGetIdent', [], rffi.INT) +def _emulated_start_new_thread(func): + "NOT_RPYTHON" + import thread + try: + ident = thread.start_new_thread(func, ()) + except thread.error: + ident = -1 + return rffi.cast(rffi.INT, ident) + +CALLBACK = lltype.Ptr(lltype.FuncType([], lltype.Void)) +c_thread_start = llexternal('RPyThreadStart', [CALLBACK], rffi.INT, + _callable=_emulated_start_new_thread, + threadsafe=True) # release the GIL, but most + # importantly, reacquire it + # around the callback +c_thread_get_ident = llexternal('RPyThreadGetIdent', [], rffi.INT, + _nowrapper=True) # always call directly TLOCKP = rffi.COpaquePtr('struct RPyOpaque_ThreadLock', compilation_info=eci) c_thread_lock_init = llexternal('RPyThreadLockInit', [TLOCKP], lltype.Void) c_thread_acquirelock = llexternal('RPyThreadAcquireLock', [TLOCKP, rffi.INT], - rffi.INT) -c_thread_releaselock = llexternal('RPyThreadReleaseLock', [TLOCKP], lltype.Void) + rffi.INT, + threadsafe=True) # release the GIL +c_thread_releaselock = llexternal('RPyThreadReleaseLock', [TLOCKP], lltype.Void, + threadsafe=True) # release the GIL # another set of functions, this time in versions that don't cause the # GIL to be released. To use to handle the GIL lock itself. c_thread_acquirelock_NOAUTO = llexternal('RPyThreadAcquireLock', [TLOCKP, rffi.INT], rffi.INT, - threadsafe=False) + _nowrapper=True) c_thread_releaselock_NOAUTO = llexternal('RPyThreadReleaseLock', [TLOCKP], lltype.Void, - threadsafe=False) -c_thread_fused_releaseacquirelock_NOAUTO = llexternal( - 'RPyThreadFusedReleaseAcquireLock', [TLOCKP], lltype.Void, - threadsafe=False) + _nowrapper=True) -def allocate_lock(): - ll_lock = lltype.malloc(TLOCKP.TO, flavor='raw') - res = c_thread_lock_init(ll_lock) - if res == -1: - lltype.free(ll_lock, flavor='raw') - raise error("out of resources") - return Lock(ll_lock) +# this function does nothing apart from releasing the GIL temporarily. +yield_thread = llexternal('RPyThreadYield', [], lltype.Void, threadsafe=True) -def allocate_lock_NOAUTO(): - ll_lock = lltype.malloc(TLOCKP.TO, flavor='raw') - res = c_thread_lock_init(ll_lock) - if res == -1: - lltype.free(ll_lock, flavor='raw') - raise error("out of resources") - return Lock_NOAUTO(ll_lock) - -def _start_new_thread(x, y): - return thread.start_new_thread(x, (y,)) +def allocate_lock(): + return Lock(allocate_ll_lock()) -def ll_start_new_thread(l_func, arg): - l_arg = cast_instance_to_base_ptr(arg) - l_arg = rffi.cast(rffi.VOIDP, l_arg) - ident = c_thread_start(l_func, l_arg) +def ll_start_new_thread(func): + ident = c_thread_start(func) if ident == -1: raise error("can't start new thread") return ident -class LLStartNewThread(ExtRegistryEntry): - _about_ = _start_new_thread - - def compute_result_annotation(self, s_func, s_arg): - bookkeeper = self.bookkeeper - s_result = bookkeeper.emulate_pbc_call(bookkeeper.position_key, - s_func, [s_arg]) - assert annmodel.s_None.contains(s_result) - return annmodel.SomeInteger() - - def specialize_call(self, hop): - rtyper = hop.rtyper - bk = rtyper.annotator.bookkeeper - r_result = rtyper.getrepr(hop.s_result) - hop.exception_is_here() - args_r = [rtyper.getrepr(s_arg) for s_arg in hop.args_s] - _callable = hop.args_s[0].const - funcptr = lltype.functionptr(CALLBACK.TO, _callable.func_name, - _callable=_callable) - func_s = bk.immutablevalue(funcptr) - s_args = [func_s, hop.args_s[1]] - obj = rtyper.getannmixlevel().delayedfunction( - ll_start_new_thread, s_args, annmodel.SomeInteger()) - bootstrap = rtyper.getannmixlevel().delayedfunction( - _callable, [hop.args_s[1]], annmodel.s_None) - vlist = [hop.inputconst(typeOf(obj), obj), - hop.inputconst(typeOf(bootstrap), bootstrap), - #hop.inputarg(args_r[0], 0), - hop.inputarg(args_r[1], 1)] - return hop.genop('direct_call', vlist, r_result) - # wrappers... def get_ident(): - return c_thread_get_ident() + return rffi.cast(lltype.Signed, c_thread_get_ident()) def start_new_thread(x, y): - return _start_new_thread(x, y[0]) + """In RPython, no argument can be passed. You have to use global + variables to pass information to the new thread. That's not very + nice, but at least it avoids some levels of GC issues. + """ + assert len(y) == 0 + return rffi.cast(lltype.Signed, ll_start_new_thread(x)) class Lock(object): """ Container for low-level implementation @@ -129,7 +105,9 @@ self._lock = ll_lock def acquire(self, flag): - return bool(c_thread_acquirelock(self._lock, int(flag))) + res = c_thread_acquirelock(self._lock, int(flag)) + res = rffi.cast(lltype.Signed, res) + return bool(res) def release(self): # Sanity check: the lock must be locked @@ -142,23 +120,58 @@ def __del__(self): lltype.free(self._lock, flavor='raw') -class Lock_NOAUTO(object): - """A special lock that doesn't cause the GIL to be released when - we try to acquire it. Used for the GIL itself.""" +# ____________________________________________________________ +# +# GIL support wrappers - def __init__(self, ll_lock): - self._lock = ll_lock - - def acquire(self, flag): - return bool(c_thread_acquirelock_NOAUTO(self._lock, int(flag))) +null_ll_lock = lltype.nullptr(TLOCKP.TO) - def release(self): - ll_assert(not self.acquire(False), "Lock_NOAUTO was not held!") - c_thread_releaselock_NOAUTO(self._lock) +def allocate_ll_lock(): + ll_lock = lltype.malloc(TLOCKP.TO, flavor='raw') + res = c_thread_lock_init(ll_lock) + if res == -1: + lltype.free(ll_lock, flavor='raw') + raise error("out of resources") + return ll_lock - def fused_release_acquire(self): - ll_assert(not self.acquire(False), "Lock_NOAUTO was not held!") - c_thread_fused_releaseacquirelock_NOAUTO(self._lock) +def acquire_NOAUTO(ll_lock, flag): + flag = rffi.cast(rffi.INT, int(flag)) + res = c_thread_acquirelock_NOAUTO(ll_lock, flag) + res = rffi.cast(lltype.Signed, res) + return bool(res) + +def release_NOAUTO(ll_lock): + if not we_are_translated(): + ll_assert(not acquire_NOAUTO(ll_lock, False), "NOAUTO lock not held!") + c_thread_releaselock_NOAUTO(ll_lock) + +# ____________________________________________________________ +# +# Thread integration. +# These are three completely ad-hoc operations at the moment. + +def gc_thread_prepare(): + """To call just before thread.start_new_thread(). This + allocates a new shadow stack to be used by the future + thread. If memory runs out, this raises a MemoryError + (which can be handled by the caller instead of just getting + ignored if it was raised in the newly starting thread). + """ + if we_are_translated(): + llop.gc_thread_prepare(lltype.Void) - def __del__(self): - lltype.free(self._lock, flavor='raw') +def gc_thread_run(): + """To call whenever the current thread (re-)acquired the GIL. + """ + if we_are_translated(): + llop.gc_thread_run(lltype.Void) +gc_thread_run._always_inline_ = True + +def gc_thread_die(): + """To call just before the final GIL release done by a dying + thread. After a thread_die(), no more gc operation should + occur in this thread. + """ + if we_are_translated(): + llop.gc_thread_die(lltype.Void) +gc_thread_die._always_inline_ = True Modified: pypy/dist/pypy/module/thread/os_thread.py ============================================================================== --- pypy/dist/pypy/module/thread/os_thread.py (original) +++ pypy/dist/pypy/module/thread/os_thread.py Wed May 28 19:48:56 2008 @@ -9,38 +9,107 @@ from pypy.interpreter.gateway import ObjSpace, W_Root, Arguments from pypy.rlib.objectmodel import free_non_gc_object -# This code has subtle memory management issues in order to start -# a new thread. It should work correctly with Boehm, but the framework -# GC will not see the references stored in the raw-malloced Bootstrapper -# instances => crash. It crashes with refcounting too -# (see the skipped test_raw_instance_flavor in -# rpython/memory/gctransformer/test/test_refcounting). +# Here are the steps performed to start a new thread: +# +# * The bootstrapper.lock is first acquired to prevent two parallel +# starting threads from messing with each other's start-up data. +# +# * The start-up data (the app-level callable and arguments) is +# stored in the global bootstrapper object. +# +# * The GC is notified that a new thread is about to start; in the +# framework GC, this allocates a fresh new shadow stack (but doesn't +# use it yet). See gc_thread_prepare(). +# +# * The new thread is launched at RPython level using an rffi call +# to the C function RPyThreadStart() defined in +# translator/c/src/thread*.h. This RPython thread will invoke the +# static method bootstrapper.bootstrap() as a call-back. +# +# * As if it was a regular callback, rffi adds a wrapper around +# bootstrap(). This wrapper acquires and releases the GIL. In this +# way the new thread is immediately GIL-protected. +# +# * As soon as the GIL is acquired in the new thread, the gc_thread_run() +# operation is called (this is all done by gil.after_external_call(), +# called from the rffi-generated wrapper). The gc_thread_run() +# operation will automatically notice that the current thread id was +# not seen before, and start using the freshly prepared shadow stack. +# +# * Only then does bootstrap() really run. The first thing it does +# is grab the start-up information (app-level callable and args) +# out of the global bootstrapper object and release bootstrapper.lock. +# Then it calls the app-level callable, to actually run the thread. +# +# * After each potential thread switch, as soon as the GIL is re-acquired, +# gc_thread_run() is called again; it ensures that the currently +# installed shadow stack is the correct one for the currently running +# thread. +# +# * Just before a thread finishes, gc_thread_die() is called to free +# its shadow stack. + class Bootstrapper(object): - _alloc_flavor_ = 'raw' - - def bootstrap(self): - space = self.space + "A global container used to pass information to newly starting threads." + + # Passing a closure argument to ll_thread.start_new_thread() would be + # theoretically nicer, but comes with messy memory management issues. + # This is much more straightforward. + + # The following lock is held whenever the fields + # 'bootstrapper.w_callable' and 'bootstrapper.args' are in use. + lock = None + + def setup(space): + if bootstrapper.lock is None: + try: + bootstrapper.lock = thread.allocate_lock() + except thread.error: + raise wrap_thread_error(space, "can't allocate bootstrap lock") + setup = staticmethod(setup) + + def bootstrap(): + # Note that when this runs, we already hold the GIL. This is ensured + # by rffi's callback mecanism: we are a callback for the + # c_thread_start() external function. + space = bootstrapper.space + w_callable = bootstrapper.w_callable + args = bootstrapper.args + bootstrapper.release() + # run! space.threadlocals.enter_thread(space) try: - self.run() + bootstrapper.run(space, w_callable, args) finally: - # release ownership of these objects before we release the GIL. - # (for the refcounting gc it is necessary to reset the fields to - # None before we use free_non_gc_object(), because the latter - # doesn't know that it needs to decref the fields) - self.args = None - self.w_callable = None - # we can free the empty 'self' structure now - free_non_gc_object(self) # clean up space.threadlocals to remove the ExecutionContext - # entry corresponding to the current thread and release the GIL - space.threadlocals.leave_thread(space) + # entry corresponding to the current thread + try: + space.threadlocals.leave_thread(space) + finally: + thread.gc_thread_die() + bootstrap = staticmethod(bootstrap) + + def acquire(space, w_callable, args): + # If the previous thread didn't start yet, wait until it does. + # Note that bootstrapper.lock must be a regular lock, not a NOAUTO + # lock, because the GIL must be released while we wait. + bootstrapper.lock.acquire(True) + bootstrapper.space = space + bootstrapper.w_callable = w_callable + bootstrapper.args = args + acquire = staticmethod(acquire) + + def release(): + # clean up 'bootstrapper' to make it ready for the next + # start_new_thread() and release the lock to tell that there + # isn't any bootstrapping thread left. + bootstrapper.w_callable = None + bootstrapper.args = None + bootstrapper.lock.release() + release = staticmethod(release) - def run(self): - space = self.space - w_callable = self.w_callable - args = self.args + def run(space, w_callable, args): try: space.call_args(w_callable, args) except OperationError, e: @@ -49,10 +118,14 @@ where = 'thread %d started by ' % ident e.write_unraisable(space, where, w_callable) e.clear(space) + run = staticmethod(run) + +bootstrapper = Bootstrapper() def setup_threads(space): space.threadlocals.setup_threads(space) + bootstrapper.setup(space) def start_new_thread(space, w_callable, w_args, w_kwargs=NoneNotWrapped): @@ -74,12 +147,14 @@ space.wrap("first arg must be callable")) args = Arguments.frompacked(space, w_args, w_kwargs) - boot = Bootstrapper() - boot.space = space - boot.w_callable = w_callable - boot.args = args + bootstrapper.acquire(space, w_callable, args) try: - ident = thread.start_new_thread(Bootstrapper.bootstrap, (boot,)) + try: + thread.gc_thread_prepare() + ident = thread.start_new_thread(bootstrapper.bootstrap, ()) + except Exception, e: + bootstrapper.release() # normally called by the new thread + raise except thread.error: raise wrap_thread_error(space, "can't start new thread") return space.wrap(ident) Modified: pypy/dist/pypy/module/thread/test/support.py ============================================================================== --- pypy/dist/pypy/module/thread/test/support.py (original) +++ pypy/dist/pypy/module/thread/test/support.py Wed May 28 19:48:56 2008 @@ -2,6 +2,7 @@ import time, gc from pypy.conftest import gettestobjspace, option from pypy.interpreter.gateway import ObjSpace, W_Root, interp2app_temp +from pypy.module.thread import gil NORMAL_TIMEOUT = 300.0 # 5 minutes @@ -10,10 +11,9 @@ adaptivedelay = 0.04 limit = time.time() + delay * NORMAL_TIMEOUT while time.time() <= limit: - GIL = space.threadlocals.GIL - GIL.release() + gil.before_external_call() time.sleep(adaptivedelay) - GIL.acquire(True) + gil.after_external_call() gc.collect() if space.is_true(space.call_function(w_condition)): return Added: pypy/dist/pypy/module/thread/test/test_gil.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/module/thread/test/test_gil.py Wed May 28 19:48:56 2008 @@ -0,0 +1,83 @@ +import time +from pypy.module.thread import gil +from pypy.module.thread.test import test_ll_thread +from pypy.rpython.lltypesystem import rffi +from pypy.module.thread import ll_thread as thread +from pypy.rlib.objectmodel import we_are_translated + +class FakeEC(object): + pass + +class FakeSpace(object): + def __init__(self): + self.pending_actions = [] + def _freeze_(self): + return True + def getexecutioncontext(self): + return FakeEC() + def getbuiltinmodule(self, name): + raise NotImplementedError + + +class GILTests(test_ll_thread.AbstractGCTestClass): + use_threads = True + bigtest = False + + def test_one_thread(self): + if self.bigtest: + N = 1000000 + else: + N = 100 + space = FakeSpace() + class State: + pass + state = State() + def runme(): + for i in range(N): + state.data.append((thread.get_ident(), i)) + state.threadlocals.yield_thread() + def bootstrap(): + try: + runme() + finally: + thread.gc_thread_die() + def f(): + state.data = [] + state.threadlocals = gil.GILThreadLocals() + state.threadlocals.setup_threads(space) + thread.gc_thread_prepare() + subident = thread.start_new_thread(bootstrap, ()) + mainident = thread.get_ident() + runme() + still_waiting = 3000 + while len(state.data) < 2*N: + if not still_waiting: + raise ValueError("time out") + still_waiting -= 1 + if not we_are_translated(): gil.before_external_call() + time.sleep(0.01) + if not we_are_translated(): gil.after_external_call() + i1 = i2 = 0 + for tid, i in state.data: + if tid == mainident: + assert i == i1; i1 += 1 + elif tid == subident: + assert i == i2; i2 += 1 + else: + assert 0 + assert i1 == N + assert i2 == N + return len(state.data) + + fn = self.getcompiled(f, []) + res = fn() + assert res == 2*N + + +class TestRunDirectly(GILTests): + def getcompiled(self, f, argtypes): + return f + +class TestUsingFramework(GILTests): + gcpolicy = 'generation' + bigtest = True Modified: pypy/dist/pypy/module/thread/test/test_ll_thread.py ============================================================================== --- pypy/dist/pypy/module/thread/test/test_ll_thread.py (original) +++ pypy/dist/pypy/module/thread/test/test_ll_thread.py Wed May 28 19:48:56 2008 @@ -1,11 +1,15 @@ - +import gc from pypy.module.thread.ll_thread import * from pypy.translator.c.test.test_boehm import AbstractGCTestClass -from pypy.rpython.lltypesystem import lltype -from pypy.rpython.lltypesystem.lloperation import llop -from pypy.rlib.objectmodel import free_non_gc_object +from pypy.rpython.lltypesystem import lltype, rffi import py +def setup_module(mod): + # Hack to avoid a deadlock if the module is run after other test files :-( + # In this module, we assume that ll_thread.start_new_thread() is not + # providing us with a GIL equivalent. + rffi.aroundstate._freeze_() + def test_lock(): l = allocate_lock() ok1 = l.acquire(True) @@ -24,19 +28,9 @@ else: py.test.fail("Did not raise") -def test_fused(): - l = allocate_lock_NOAUTO() - l.acquire(True) - l.fused_release_acquire() - could_acquire_again = l.acquire(False) - assert not could_acquire_again - l.release() - could_acquire_again = l.acquire(False) - assert could_acquire_again - -class TestUsingBoehm(AbstractGCTestClass): - gcpolicy = 'boehm' +class AbstractThreadTests(AbstractGCTestClass): + use_threads = True def test_start_new_thread(self): import time @@ -51,21 +45,16 @@ def __del__(self): state.freed_counter += 1 - class Y: - _alloc_flavor_ = 'raw' - - def bootstrap(self): - state.my_thread_ident = get_ident() - assert state.my_thread_ident == get_ident() - state.seen_value = self.z.value - self.z = None - free_non_gc_object(self) - state.done = 1 + def bootstrap(): + state.my_thread_ident = get_ident() + assert state.my_thread_ident == get_ident() + state.seen_value = state.z.value + state.z = None + state.done = 1 def g(i): - y = Y() - y.z = Z(i) - start_new_thread(Y.bootstrap, (y,)) + state.z = Z(i) + start_new_thread(bootstrap, ()) g._dont_inline_ = True def f(): @@ -76,6 +65,7 @@ state.done = 0 state.seen_value = 0 g(i) + gc.collect() willing_to_wait_more = 1000 while not state.done: willing_to_wait_more -= 1 @@ -86,7 +76,7 @@ assert state.seen_value == i # try to force Boehm to do some freeing for i in range(3): - llop.gc__collect(lltype.Void) + gc.collect() return state.freed_counter fn = self.getcompiled(f, []) @@ -110,34 +100,43 @@ self.j = j def run(self): j = self.j - state.gil.acquire(True) - assert j == self.j if self.i > 1: g(self.i-1, self.j * 2) + assert j == self.j g(self.i-2, self.j * 2 + 1) else: - state.answers.append(self.i) - assert j == self.j - state.gil.release() + if len(state.answers) % 7 == 5: + gc.collect() + state.answers.append(self.j) assert j == self.j run._dont_inline_ = True - class Y(object): - _alloc_flavor_ = 'raw' - def bootstrap(self): - self.z.run() - self.z = None - free_non_gc_object(self) - state.done = 1 + def bootstrap(): + acquire_NOAUTO(state.gil, True) + gc_thread_run() + z = state.z + state.z = None + z.run() + gc_thread_die() + release_NOAUTO(state.gil) def g(i, j): - y = Y() - y.z = Z(i, j) - start_new_thread(Y.bootstrap, (y,)) - g._dont_inline_ = True + state.z = Z(i, j) + gc_thread_prepare() + start_new_thread(bootstrap, ()) + # now wait until the new thread really started and consumed 'z' + willing_to_wait_more = 1000 + while state.z is not None: + assert willing_to_wait_more > 0 + willing_to_wait_more -= 1 + release_NOAUTO(state.gil) + time.sleep(0.005) + acquire_NOAUTO(state.gil, True) + gc_thread_run() def f(): - state.gil = allocate_lock_NOAUTO() + state.gil = allocate_ll_lock() + acquire_NOAUTO(state.gil, True) state.answers = [] state.finished = 0 g(7, 1) @@ -149,10 +148,12 @@ " expected %d" % (len(state.answers), expected)) willing_to_wait_more -= 1 - state.gil.acquire(True) done = len(state.answers) == expected - state.gil.release() + release_NOAUTO(state.gil) time.sleep(0.01) + acquire_NOAUTO(state.gil, True) + gc_thread_run() + release_NOAUTO(state.gil) time.sleep(0.1) return len(state.answers) @@ -161,8 +162,12 @@ answers = fn() assert answers == expected -class TestUsingFramework(TestUsingBoehm): - gcpolicy = 'generation' +class TestRunDirectly(AbstractThreadTests): + def getcompiled(self, f, argtypes): + return f - def test_gc_locking(self): - py.test.skip("in-progress") +class TestUsingBoehm(AbstractThreadTests): + gcpolicy = 'boehm' + +class TestUsingFramework(AbstractThreadTests): + gcpolicy = 'generation' Modified: pypy/dist/pypy/module/thread/threadlocals.py ============================================================================== --- pypy/dist/pypy/module/thread/threadlocals.py (original) +++ pypy/dist/pypy/module/thread/threadlocals.py Wed May 28 19:48:56 2008 @@ -52,7 +52,3 @@ def atthreadexit(self, space, exit_func, w_obj): ec = space.getexecutioncontext() ec.thread_exit_funcs.append((exit_func, w_obj)) - - def getGIL(self): - return None - Modified: pypy/dist/pypy/rlib/rposix.py ============================================================================== --- pypy/dist/pypy/rlib/rposix.py (original) +++ pypy/dist/pypy/rlib/rposix.py Wed May 28 19:48:56 2008 @@ -1,6 +1,6 @@ import os from pypy.rpython.lltypesystem.rffi import CConstant, CExternVariable, INT -from pypy.rpython.lltypesystem import lltype, ll2ctypes +from pypy.rpython.lltypesystem import lltype, ll2ctypes, rffi from pypy.translator.tool.cbuild import ExternalCompilationInfo from pypy.rlib.rarithmetic import intmask @@ -22,12 +22,19 @@ includes=['errno.h'] ) -_get_errno, set_errno = CExternVariable(INT, 'errno', errno_eci, - CConstantErrno, sandboxsafe=True) +_get_errno, _set_errno = CExternVariable(INT, 'errno', errno_eci, + CConstantErrno, sandboxsafe=True, + _nowrapper=True) +# the default wrapper for set_errno is not suitable for use in critical places +# like around GIL handling logic, so we provide our own wrappers. def get_errno(): return intmask(_get_errno()) +def set_errno(errno): + _set_errno(rffi.cast(INT, errno)) + + def closerange(fd_low, fd_high): # this behaves like os.closerange() from Python 2.6. for fd in xrange(fd_low, fd_high): Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Wed May 28 19:48:56 2008 @@ -774,6 +774,15 @@ addr = llmemory.cast_ptr_to_adr(ptr) return self.heap.can_move(addr) + def op_gc_thread_prepare(self): + self.heap.thread_prepare() + + def op_gc_thread_run(self): + self.heap.thread_run() + + def op_gc_thread_die(self): + self.heap.thread_die() + def op_gc_free(self, addr): # what can you do? pass Modified: pypy/dist/pypy/rpython/lltypesystem/llheap.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/llheap.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/llheap.py Wed May 28 19:48:56 2008 @@ -34,3 +34,12 @@ for i in range(final_size): ll_str.chars[i] = buf.chars[i] return ll_str + +def thread_prepare(): + pass + +def thread_run(): + pass + +def thread_die(): + pass Modified: pypy/dist/pypy/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/lloperation.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/lloperation.py Wed May 28 19:48:56 2008 @@ -406,6 +406,9 @@ 'gc_id': LLOp(canraise=(MemoryError,), sideeffects=False), 'gc_set_max_heap_size': LLOp(), 'gc_can_move' : LLOp(sideeffects=False), + 'gc_thread_prepare' : LLOp(canraise=(MemoryError,)), + 'gc_thread_run' : LLOp(), + 'gc_thread_die' : LLOp(), # experimental operations in support of thread cloning, only # implemented by the Mark&Sweep GC 'gc_x_swap_pool': LLOp(canraise=(MemoryError,), canunwindgc=True), Modified: pypy/dist/pypy/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rffi.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rffi.py Wed May 28 19:48:56 2008 @@ -146,6 +146,10 @@ if before: before() # NB. it is essential that no exception checking occurs after # the call to before(), because we don't have the GIL any more! + # It is also essential that no GC pointer is alive between now + # and the end of the function, so that the external function + # calls below don't need to be guarded by GC shadow stack logic + # that would crash if not protected by the GIL! res = funcptr(*real_args) if invoke_around_handlers: if after: after() @@ -159,7 +163,12 @@ return cast(lltype.Unsigned, res) return res wrapper._annspecialcase_ = 'specialize:ll' - wrapper._always_inline_ = True + if invoke_around_handlers: + # don't inline, as a hack to guarantee that no GC pointer is alive + # in the final part of the wrapper + wrapper._dont_inline_ = True + else: + wrapper._always_inline_ = True # for debugging, stick ll func ptr to that wrapper._ptr = funcptr @@ -173,16 +182,16 @@ errorcode = callable._errorcode_ else: errorcode = TP.TO.RESULT._example() - if aroundstate is not None: - before = aroundstate.before - after = aroundstate.after - else: - before = None - after = None callable_name = getattr(callable, '__name__', '?') args = ', '.join(['a%d' % i for i in range(len(TP.TO.ARGS))]) source = py.code.Source(r""" def wrapper(%s): # no *args - no GIL for mallocing the tuple + if aroundstate is not None: + before = aroundstate.before + after = aroundstate.after + else: + before = None + after = None if after: after() # from now on we hold the GIL @@ -192,6 +201,9 @@ os.write(2, "Warning: uncaught exception in callback: %%s %%s\n" %% (callable_name, str(e))) + if not we_are_translated(): + import traceback + traceback.print_exc() result = errorcode if before: before() @@ -203,6 +215,7 @@ miniglobals = locals().copy() miniglobals['Exception'] = Exception miniglobals['os'] = os + miniglobals['we_are_translated'] = we_are_translated exec source.compile() in miniglobals return miniglobals['wrapper'] _make_wrapper_for._annspecialcase_ = 'specialize:memo' @@ -378,7 +391,7 @@ return lltype.Ptr(COpaque(*args, **kwds)) def CExternVariable(TYPE, name, eci, _CConstantClass=CConstant, - sandboxsafe=False): + sandboxsafe=False, _nowrapper=False): """Return a pair of functions - a getter and a setter - to access the given global C variable. """ @@ -417,9 +430,10 @@ )) getter = llexternal(getter_name, [], TYPE, compilation_info=new_eci, - sandboxsafe=sandboxsafe) + sandboxsafe=sandboxsafe, _nowrapper=_nowrapper) setter = llexternal(setter_name, [TYPE], lltype.Void, - compilation_info=new_eci, sandboxsafe=sandboxsafe) + compilation_info=new_eci, sandboxsafe=sandboxsafe, + _nowrapper=_nowrapper) return getter, setter # char, represented as a Python character Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_rffi.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/test/test_rffi.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/test/test_rffi.py Wed May 28 19:48:56 2008 @@ -531,7 +531,8 @@ assert interpret(f, []) == 3 def test_implicit_cast(self): - z = llexternal('z', [USHORT, ULONG, USHORT, DOUBLE], USHORT) + z = llexternal('z', [USHORT, ULONG, USHORT, DOUBLE], USHORT, + sandboxsafe=True) # to allow the wrapper to be inlined def f(x, y, xx, yy): return z(x, y, xx, yy) Modified: pypy/dist/pypy/rpython/memory/gctransform/framework.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gctransform/framework.py (original) +++ pypy/dist/pypy/rpython/memory/gctransform/framework.py Wed May 28 19:48:56 2008 @@ -22,6 +22,16 @@ class CollectAnalyzer(graphanalyze.GraphAnalyzer): + + def analyze_direct_call(self, graph, seen=None): + try: + if graph.func._gctransformer_hint_cannot_collect_: + return False + except AttributeError: + pass + return graphanalyze.GraphAnalyzer.analyze_direct_call(self, graph, + seen) + def operation_is_true(self, op): if op.opname in ('malloc', 'malloc_varsize'): flags = op.args[1].value @@ -343,6 +353,20 @@ annmodel.s_None, minimal_transform = False) + # thread support + if translator.config.translation.thread: + if not hasattr(root_walker, "need_thread_support"): + raise Exception("%s does not support threads" % ( + root_walker.__class__.__name__,)) + root_walker.need_thread_support() + self.thread_prepare_ptr = getfn(root_walker.thread_prepare, + [], annmodel.s_None) + self.thread_run_ptr = getfn(root_walker.thread_run, + [], annmodel.s_None, + inline=True) + self.thread_die_ptr = getfn(root_walker.thread_die, + [], annmodel.s_None) + annhelper.finish() # at this point, annotate all mix-level helpers annhelper.backend_optimize() @@ -645,6 +669,18 @@ self.c_const_gc, v_size]) + def gct_gc_thread_prepare(self, hop): + assert self.translator.config.translation.thread + hop.genop("direct_call", [self.thread_prepare_ptr]) + + def gct_gc_thread_run(self, hop): + assert self.translator.config.translation.thread + hop.genop("direct_call", [self.thread_run_ptr]) + + def gct_gc_thread_die(self, hop): + assert self.translator.config.translation.thread + hop.genop("direct_call", [self.thread_die_ptr]) + def gct_malloc_nonmovable_varsize(self, hop): TYPE = hop.spaceop.result.concretetype if self.gcdata.gc.can_malloc_nonmovable(): @@ -836,6 +872,8 @@ class ShadowStackRootWalker(BaseRootWalker): need_root_stack = True + thread_setup = None + collect_stacks_from_other_threads = None def __init__(self, gctransformer): BaseRootWalker.__init__(self, gctransformer) @@ -855,12 +893,27 @@ return top self.decr_stack = decr_stack + def push_stack(self, addr): + top = self.incr_stack(1) + top.address[0] = addr + + def pop_stack(self): + top = self.decr_stack(1) + return top.address[0] + + def allocate_stack(self): + result = llmemory.raw_malloc(self.rootstacksize) + if result: + llmemory.raw_memclear(result, self.rootstacksize) + return result + def setup_root_walker(self): - stackbase = llmemory.raw_malloc(self.rootstacksize) + stackbase = self.allocate_stack() ll_assert(bool(stackbase), "could not allocate root stack") - llmemory.raw_memclear(stackbase, self.rootstacksize) self.gcdata.root_stack_top = stackbase self.gcdata.root_stack_base = stackbase + if self.thread_setup is not None: + self.thread_setup() def walk_stack_roots(self, collect_stack_root): gcdata = self.gcdata @@ -871,3 +924,121 @@ if addr.address[0] != llmemory.NULL: collect_stack_root(gc, addr) addr += sizeofaddr + if self.collect_stacks_from_other_threads is not None: + self.collect_stacks_from_other_threads(collect_stack_root) + + def need_thread_support(self): + from pypy.module.thread import ll_thread # xxx fish + from pypy.rpython.memory.support import AddressDict + from pypy.rpython.memory.support import copy_without_null_values + gcdata = self.gcdata + # the interfacing between the threads and the GC is done via + # three completely ad-hoc operations at the moment: + # gc_thread_prepare, gc_thread_run, gc_thread_die. + # See docstrings below. + + def get_aid(): + """Return the thread identifier, cast to an (opaque) address.""" + return llmemory.cast_int_to_adr(ll_thread.get_ident()) + + def thread_setup(): + """Called once when the program starts.""" + aid = get_aid() + gcdata.main_thread = aid + gcdata.active_thread = aid + gcdata.thread_stacks = AddressDict() # {aid: root_stack_top} + gcdata._fresh_rootstack = llmemory.NULL + gcdata.dead_threads_count = 0 + + def thread_prepare(): + """Called just before thread.start_new_thread(). This + allocates a new shadow stack to be used by the future + thread. If memory runs out, this raises a MemoryError + (which can be handled by the caller instead of just getting + ignored if it was raised in the newly starting thread). + """ + if not gcdata._fresh_rootstack: + gcdata._fresh_rootstack = self.allocate_stack() + if not gcdata._fresh_rootstack: + raise MemoryError + + def thread_run(): + """Called whenever the current thread (re-)acquired the GIL. + This should ensure that the shadow stack installed in + gcdata.root_stack_top/root_stack_base is the one corresponding + to the current thread. + """ + aid = get_aid() + if gcdata.active_thread != aid: + switch_shadow_stacks(aid) + + def thread_die(): + """Called just before the final GIL release done by a dying + thread. After a thread_die(), no more gc operation should + occur in this thread. + """ + aid = get_aid() + gcdata.thread_stacks.setitem(aid, llmemory.NULL) + old = gcdata.root_stack_base + if gcdata._fresh_rootstack == llmemory.NULL: + gcdata._fresh_rootstack = old + else: + llmemory.raw_free(old) + install_new_stack(gcdata.main_thread) + # from time to time, rehash the dictionary to remove + # old NULL entries + gcdata.dead_threads_count += 1 + if (gcdata.dead_threads_count & 511) == 0: + gcdata.thread_stacks = copy_without_null_values( + gcdata.thread_stacks) + + def switch_shadow_stacks(new_aid): + save_away_current_stack() + install_new_stack(new_aid) + switch_shadow_stacks._dont_inline_ = True + + def save_away_current_stack(): + old_aid = gcdata.active_thread + # save root_stack_base on the top of the stack + self.push_stack(gcdata.root_stack_base) + # store root_stack_top into the dictionary + gcdata.thread_stacks.setitem(old_aid, gcdata.root_stack_top) + + def install_new_stack(new_aid): + # look for the new stack top + top = gcdata.thread_stacks.get(new_aid, llmemory.NULL) + if top == llmemory.NULL: + # first time we see this thread. It is an error if no + # fresh new stack is waiting. + base = gcdata._fresh_rootstack + gcdata._fresh_rootstack = llmemory.NULL + ll_assert(base != llmemory.NULL, "missing gc_thread_prepare") + gcdata.root_stack_top = base + gcdata.root_stack_base = base + else: + # restore the root_stack_base from the top of the stack + gcdata.root_stack_top = top + gcdata.root_stack_base = self.pop_stack() + # done + gcdata.active_thread = new_aid + + def collect_stack(aid, stacktop, callback): + if stacktop != llmemory.NULL and aid != get_aid(): + # collect all valid stacks from the dict (the entry + # corresponding to the current thread is not valid) + gc = self.gc + end = stacktop - sizeofaddr + addr = end.address[0] + while addr != end: + if addr.address[0] != llmemory.NULL: + callback(gc, addr) + addr += sizeofaddr + + def collect_more_stacks(callback): + gcdata.thread_stacks.foreach(collect_stack, callback) + + self.thread_setup = thread_setup + self.thread_prepare = thread_prepare + self.thread_run = thread_run + self.thread_die = thread_die + self.collect_stacks_from_other_threads = collect_more_stacks Modified: pypy/dist/pypy/rpython/memory/support.py ============================================================================== --- pypy/dist/pypy/rpython/memory/support.py (original) +++ pypy/dist/pypy/rpython/memory/support.py Wed May 28 19:48:56 2008 @@ -305,3 +305,19 @@ arg.setitem(newkey, value) return callback _get_updater._annspecialcase_ = 'specialize:memo' + + +def copy_without_null_values(dict): + """Make a copy of 'dict' without the key/value pairs where value==NULL.""" + newdict = AddressDict + if not we_are_translated(): + # when not translated, return a dict of the same kind as 'dict' + if not isinstance(dict, BasicAddressDict): + from pypy.rpython.memory.lldict import newdict + result = newdict() + dict.foreach(_null_value_checker, result) + return result + +def _null_value_checker(key, value, arg): + if value: + arg.setitem(key, value) Modified: pypy/dist/pypy/translator/c/gc.py ============================================================================== --- pypy/dist/pypy/translator/c/gc.py (original) +++ pypy/dist/pypy/translator/c/gc.py Wed May 28 19:48:56 2008 @@ -72,6 +72,15 @@ def OP_GC_SET_MAX_HEAP_SIZE(self, funcgen, op): return '' + def OP_GC_THREAD_PREPARE(self, funcgen, op): + return '' + + def OP_GC_THREAD_RUN(self, funcgen, op): + return '' + + def OP_GC_THREAD_DIE(self, funcgen, op): + return '' + class RefcountingInfo: static_deallocator = None Modified: pypy/dist/pypy/translator/c/src/thread.h ============================================================================== --- pypy/dist/pypy/translator/c/src/thread.h (original) +++ pypy/dist/pypy/translator/c/src/thread.h Wed May 28 19:48:56 2008 @@ -44,17 +44,13 @@ #endif -/* common helper: this is a single external function so that we are - sure that nothing occurs between the release and the acquire, - e.g. no GC operation. */ - -void RPyThreadFusedReleaseAcquireLock(struct RPyOpaque_ThreadLock *lock); +/* common helper: this does nothing, but is called with the GIL released. + This gives other threads a chance to grab the GIL and run. */ +void RPyThreadYield(void); #ifndef PYPY_NOT_MAIN_FILE -void RPyThreadFusedReleaseAcquireLock(struct RPyOpaque_ThreadLock *lock) +void RPyThreadYield(void) { - RPyThreadReleaseLock(lock); - RPyThreadAcquireLock(lock, 1); } #endif Modified: pypy/dist/pypy/translator/c/src/thread_nt.h ============================================================================== --- pypy/dist/pypy/translator/c/src/thread_nt.h (original) +++ pypy/dist/pypy/translator/c/src/thread_nt.h Wed May 28 19:48:56 2008 @@ -22,8 +22,7 @@ #define RPyOpaque_INITEXPR_ThreadLock { 0, 0, NULL } typedef struct { - void (*func)(void*); - void *arg; + void (*func)(void); long id; HANDLE done; } callobj; @@ -35,7 +34,7 @@ } NRMUTEX, *PNRMUTEX ; /* prototypes */ -long RPyThreadStart(void (*func)(void *), void *arg); +long RPyThreadStart(void (*func)(void)); BOOL InitializeNonRecursiveMutex(PNRMUTEX mutex); VOID DeleteNonRecursiveMutex(PNRMUTEX mutex); DWORD EnterNonRecursiveMutex(PNRMUTEX mutex, BOOL wait); @@ -63,23 +62,21 @@ { callobj *obj = (callobj*)call; /* copy callobj since other thread might free it before we're done */ - void (*func)(void*) = obj->func; - void *arg = obj->arg; + void (*func)(void) = obj->func; obj->id = RPyThreadGetIdent(); ReleaseSemaphore(obj->done, 1, NULL); - func(arg); + func(); return 0; } -long RPyThreadStart(void (*func)(void *), void *arg) +long RPyThreadStart(void (*func)(void)) { unsigned long rv; callobj obj; obj.id = -1; /* guilty until proved innocent */ obj.func = func; - obj.arg = arg; obj.done = CreateSemaphore(NULL, 0, 1, NULL); if (obj.done == NULL) return -1; Modified: pypy/dist/pypy/translator/c/src/thread_pthread.h ============================================================================== --- pypy/dist/pypy/translator/c/src/thread_pthread.h (original) +++ pypy/dist/pypy/translator/c/src/thread_pthread.h Wed May 28 19:48:56 2008 @@ -75,7 +75,7 @@ /* prototypes */ long RPyThreadGetIdent(void); -long RPyThreadStart(void (*func)(void *), void *arg); +long RPyThreadStart(void (*func)(void)); int RPyThreadLockInit(struct RPyOpaque_ThreadLock *lock); void RPyOpaqueDealloc_ThreadLock(struct RPyOpaque_ThreadLock *lock); int RPyThreadAcquireLock(struct RPyOpaque_ThreadLock *lock, int waitflag); @@ -105,7 +105,13 @@ #endif } -long RPyThreadStart(void (*func)(void *), void *arg) +static void *bootstrap_pthread(void *func) +{ + ((void(*)(void))func)(); + return NULL; +} + +long RPyThreadStart(void (*func)(void)) { pthread_t th; int status; @@ -129,8 +135,8 @@ #else (pthread_attr_t*)NULL, #endif - (void* (*)(void *))func, - (void *)arg + bootstrap_pthread, + (void *)func ); #if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED) Modified: pypy/dist/pypy/translator/c/test/test_boehm.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_boehm.py (original) +++ pypy/dist/pypy/translator/c/test/test_boehm.py Wed May 28 19:48:56 2008 @@ -13,6 +13,7 @@ class AbstractGCTestClass(object): gcpolicy = "boehm" stacklessgc = False + use_threads = False # deal with cleanups def setup_method(self, meth): @@ -27,6 +28,7 @@ from pypy.config.pypyoption import get_pypy_config config = get_pypy_config(translating=True) config.translation.gc = self.gcpolicy + config.translation.thread = self.use_threads if self.stacklessgc: config.translation.gcrootfinder = "stackless" config.translation.simplifying = True From fijal at codespeak.net Wed May 28 20:17:37 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 28 May 2008 20:17:37 +0200 (CEST) Subject: [pypy-svn] r55367 - in pypy/dist/pypy/lib: . app_test Message-ID: <20080528181737.2C362169F48@codespeak.net> Author: fijal Date: Wed May 28 20:17:36 2008 New Revision: 55367 Modified: pypy/dist/pypy/lib/app_test/test_pyexpat.py pypy/dist/pypy/lib/pyexpat.py Log: A bit of error reporting. Pass all tests, even those failing on cpy 2.5 Modified: pypy/dist/pypy/lib/app_test/test_pyexpat.py ============================================================================== --- pypy/dist/pypy/lib/app_test/test_pyexpat.py (original) +++ pypy/dist/pypy/lib/app_test/test_pyexpat.py Wed May 28 20:17:36 2008 @@ -371,7 +371,6 @@ raise RuntimeError(name) def test(self): - py.test.skip("not implemented") parser = expat.ParserCreate() parser.StartElementHandler = self.StartElementHandler try: @@ -447,7 +446,8 @@ try: import __pypy__ except ImportError: - py.test.skip("Doesn't work on cpy 2.5") + pass + #py.test.skip("Doesn't work on cpy 2.5") def test_1025_bytes(self): assert self.small_buffer_test(1025) == 2 Modified: pypy/dist/pypy/lib/pyexpat.py ============================================================================== --- pypy/dist/pypy/lib/pyexpat.py (original) +++ pypy/dist/pypy/lib/pyexpat.py Wed May 28 20:17:36 2008 @@ -2,7 +2,8 @@ import ctypes import ctypes.util from ctypes_configure import configure -from ctypes import c_char_p, c_int, c_void_p, POINTER, c_char +from ctypes import c_char_p, c_int, c_void_p, POINTER, c_char, c_wchar_p +import sys lib = ctypes.CDLL(ctypes.util.find_library('expat')) @@ -21,21 +22,31 @@ 'XML_PARAM_ENTITY_PARSING_ALWAYS']: locals()[name] = configure.ConstantInteger(name) + XML_Encoding = configure.Struct('XML_Encoding',[ + ('data', c_void_p), + ('convert', c_void_p), + ('release', c_void_p), + ('map', c_int * 256)]) + # this is insanely stupid + XML_FALSE = configure.ConstantInteger('XML_FALSE') + XML_TRUE = configure.ConstantInteger('XML_TRUE') + info = configure.configure(CConfigure) for k, v in info.items(): globals()[k] = v XML_Parser = ctypes.c_void_p # an opaque pointer assert XML_Char is ctypes.c_char # this assumption is everywhere in # cpython's expat, let's explode -XML_ParserCreate = lib.XML_ParserCreate -XML_ParserCreate.args = [ctypes.c_char_p] -XML_ParserCreate.result = XML_Parser -XML_ParserCreateNS = lib.XML_ParserCreateNS -XML_ParserCreateNS.args = [c_char_p, c_char] -XML_ParserCreateNS.result = XML_Parser -XML_Parse = lib.XML_Parse -XML_Parse.args = [XML_Parser, ctypes.c_char_p, ctypes.c_int, ctypes.c_int] -XML_Parse.result = ctypes.c_int + +def declare_external(name, args, res): + func = getattr(lib, name) + func.args = args + func.result = res + globals()[name] = func + +declare_external('XML_ParserCreate', [c_char_p], XML_Parser) +declare_external('XML_ParserCreateNS', [c_char_p, c_char], XML_Parser) +declare_external('XML_Parse', [XML_Parser, c_char_p, c_int, c_int], c_int) currents = ['CurrentLineNumber', 'CurrentColumnNumber', 'CurrentByteIndex'] for name in currents: @@ -43,15 +54,22 @@ func.args = [XML_Parser] func.result = c_int -XML_SetReturnNSTriplet = lib.XML_SetReturnNSTriplet -XML_SetReturnNSTriplet.args = [XML_Parser, c_int] -XML_SetReturnNSTriplet.result = None -XML_GetSpecifiedAttributeCount = lib.XML_GetSpecifiedAttributeCount -XML_GetSpecifiedAttributeCount.args = [XML_Parser] -XML_GetSpecifiedAttributeCount.result = c_int -XML_SetParamEntityParsing = lib.XML_SetParamEntityParsing -XML_SetParamEntityParsing.args = [XML_Parser, c_int] -XML_SetParamEntityParsing.result = None +declare_external('XML_SetReturnNSTriplet', [XML_Parser, c_int], None) +declare_external('XML_GetSpecifiedAttributeCount', [XML_Parser], c_int) +declare_external('XML_SetParamEntityParsing', [XML_Parser, c_int], None) +declare_external('XML_GetErrorCode', [XML_Parser], c_int) +declare_external('XML_StopParser', [XML_Parser, c_int], None) +lib.XML_ErrorString.args = [c_int] +lib.XML_ErrorString.result = c_int + +declare_external('XML_SetUnknownEncodingHandler', [XML_Parser, c_void_p, + c_void_p], None) + +def XML_ErrorString(code): + res = lib.XML_ErrorString(code) + p = c_char_p() + p.value = res + return p.value handler_names = [ 'StartElement', @@ -92,7 +110,8 @@ setters[name] = cfunc class ExpatError(Exception): - pass + def __str__(self): + return self.s error = ExpatError @@ -111,6 +130,7 @@ self.itself = XML_ParserCreateNS(encoding, ord(namespace_separator)) if not self.itself: raise RuntimeError("Creating parser failed") + self._set_unknown_encoding_handler() self.storage = {} self.buffer = None self.buffer_size = 8192 @@ -128,10 +148,42 @@ if self.character_data_handler: self.character_data_handler(buf) - def Parse(self, data, is_final): + def _set_unknown_encoding_handler(self): + def UnknownEncoding(encodingData, name, info_p): + info = info_p.contents + s = ''.join([chr(i) for i in range(256)]) + u = s.decode(self.encoding, 'replace') + for i in range(len(u)): + if u[i] == u'\xfffd': + info.map[i] = -1 + else: + info.map[i] = ord(u[i]) + info.data = None + info.convert = None + info.release = None + return 1 + + CB = ctypes.CFUNCTYPE(c_int, c_void_p, c_char_p, POINTER(XML_Encoding)) + cb = CB(UnknownEncoding) + self._unknown_encoding_handler = (cb, UnknownEncoding) + XML_SetUnknownEncodingHandler(self.itself, cb, None) + + def _set_error(self, code): + e = ExpatError() + e.code = code + lineno = lib.XML_GetCurrentLineNumber(self.itself) + colno = lib.XML_GetCurrentColumnNumber(self.itself) + e.offset = colno + e.lineno = lineno + err = XML_ErrorString(code)[:200] + e.s = "%s: line: %d, column: %d" % (err, lineno, colno) + self._error = e + + def Parse(self, data, is_final=0): res = XML_Parse(self.itself, data, len(data), is_final) if res == 0: - xxx + self._set_error(XML_GetErrorCode(self.itself)) + raise self.__exc_info[0], self.__exc_info[1], self.__exc_info[2] self._flush_character_buffer() return res @@ -147,6 +199,15 @@ cb = getattr(self, 'get_cb_for_%s' % name)(real_cb) setter(self.itself, cb) + def _wrap_cb(self, cb): + def f(*args): + try: + return cb(*args) + except: + self.__exc_info = sys.exc_info() + XML_StopParser(self.itself, XML_FALSE) + return f + def get_cb_for_StartElementHandler(self, real_cb): def StartElement(unused, name, attrs): # unpack name and attrs @@ -165,6 +226,7 @@ for i in range(0, max, 2): res[conv(attrs[i])] = conv(attrs[i + 1]) real_cb(conv(name), res) + StartElement = self._wrap_cb(StartElement) CB = ctypes.CFUNCTYPE(None, c_void_p, c_char_p, POINTER(c_char_p)) return CB(StartElement) @@ -177,6 +239,7 @@ if res is None: return 0 return res + ExternalEntity = self._wrap_cb(ExternalEntity) CB = ctypes.CFUNCTYPE(c_int, c_void_p, *([c_char_p] * 4)) return CB(ExternalEntity) @@ -189,11 +252,12 @@ self._flush_character_buffer() if self.character_data_handler is None: return - if lgt > self.buffer_size: + if lgt >= self.buffer_size: self._call_character_handler(s[:lgt]) self.buffer = [] else: self.buffer.append(s[:lgt]) + CharacterData = self._wrap_cb(CharacterData) CB = ctypes.CFUNCTYPE(None, c_void_p, POINTER(c_char), c_int) return CB(CharacterData) @@ -206,6 +270,7 @@ pub_id, not_name] args = [self.conv(arg) for arg in args] real_cb(*args) + EntityDecl = self._wrap_cb(EntityDecl) CB = ctypes.CFUNCTYPE(None, c_void_p, c_char_p, c_int, c_char_p, c_int, c_char_p, c_char_p, c_char_p, c_char_p) return CB(EntityDecl) @@ -213,7 +278,8 @@ def get_cb_for_ElementDeclHandler(self, real_cb): # XXX this is broken, needs tests def ElementDecl(unused, *args): - pass + print "WARNING! ElementDeclHandler Not supported" + ElementDecl = self._wrap_cb(ElementDecl) CB = ctypes.CFUNCTYPE(None, c_void_p, c_char_p, c_void_p) return CB(ElementDecl) @@ -224,6 +290,7 @@ arg = self.conv(s[:len]) real_cb(arg) func.func_name = name + func = self._wrap_cb(func) CB = ctypes.CFUNCTYPE(*sign) return CB(func) get_callback_for_.func_name = 'get_cb_for_' + name @@ -242,6 +309,7 @@ args = [self.conv(arg) for arg in args] real_cb(*args) func.func_name = name + func = self._wrap_cb(func) CB = ctypes.CFUNCTYPE(*sign) return CB(func) get_callback_for_.func_name = 'get_cb_for_' + name @@ -293,6 +361,12 @@ else: self._flush_character_buffer() self.buffer = None + elif name == 'buffer_size': + if not isinstance(value, int): + raise TypeError("Expected int") + if value <= 0: + raise ValueError("Expected positive int") + self.__dict__[name] = value elif name == 'namespace_prefixes': XML_SetReturnNSTriplet(self.itself, int(bool(value))) elif name in setters: From arigo at codespeak.net Wed May 28 21:32:17 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 28 May 2008 21:32:17 +0200 (CEST) Subject: [pypy-svn] r55368 - pypy/dist/pypy/doc Message-ID: <20080528193217.7C8FE698067@codespeak.net> Author: arigo Date: Wed May 28 21:32:14 2008 New Revision: 55368 Modified: pypy/dist/pypy/doc/getting-started.txt Log: Update the paragraph about using translate.py. Thanks xoraxax Modified: pypy/dist/pypy/doc/getting-started.txt ============================================================================== --- pypy/dist/pypy/doc/getting-started.txt (original) +++ pypy/dist/pypy/doc/getting-started.txt Wed May 28 21:32:14 2008 @@ -572,34 +572,31 @@ .. _`windows document`: windows.html -You can -translate the PyPy's whole of Python interpreter to low level C code. This is -the largest and -ultimate example of source that our translation toolchain can process. -If you don't need threads, the most standard variant nowadays is:: +You can translate the whole of PyPy's Python interpreter to low level C +code. This is the largest and ultimate example of RPython program that +our translation toolchain can process. The most standard variant +nowadays is:: cd pypy/translator/goal - python translate.py --gc=hybrid targetpypystandalone.py --allworkingmodules --faassen + python translate.py --gc=hybrid --thread targetpypystandalone.py --allworkingmodules --faassen This whole process will take some time and quite a lot of memory (around 1GB). It creates an executable ``pypy-c`` in the current directory. The ``--gc=hybrid`` option means that the ``pypy-c`` will use our own exact generational garbage collector implementation, whose performance -is rather good nowadays. The ``--faassen`` option enables all the +is rather good nowadays. The ``--thread`` option enables the thread +module, which is still slightly experimental. +The ``--faassen`` option enables all the worthwhile performance optimizations, but slows down the translation -itself. On Linux 32-bit Intel machines you can also add -``--gcrootfinder=asmgcc`` after ``--gc=hybrid`` for extra speed (and -extra translation time). - -At the moment, threads only work with the `Boehm-Demers-Weiser garbage -collector`_. So to enable them, you need instead:: - - cd pypy/translator/goal - python translate.py --thread targetpypystandalone.py --allworkingmodules --faassen +itself. On Linux 32-bit Intel machines, if you don't need threads, you +can get some extra speed (and extra translation time) by removing +``--thread`` and replacing it with ``--gcrootfinder=asmgcc``. +An alternative is to use the `Boehm-Demers-Weiser garbage +collector`_ instead of our own. For this, use ``--gc=boehm``. Be sure to install Boehm before starting the translation (e.g. by running ``apt-get install libgc-dev`` on Debian or Ubuntu). Translating with Boehm -is a bit faster and less memory-hungry than translating with our own GCs. +is somewhat faster and less memory-hungry than translating with our own GCs. In any case, as described above, you can find the produced executable under the name ``pypy-c``. Type ``pypy-c --help`` to see the options it supports -- @@ -618,7 +615,7 @@ * ``--gc=boehm|ref|marknsweep|semispace|generation|hybrid``: choose between using the `Boehm-Demers-Weiser garbage collector`_, our reference - counting implementation or three of own collector implementations + counting implementation or four of own collector implementations (Boehm's collector is the default). Find a more detailed description of the various options in our `configuration From arigo at codespeak.net Wed May 28 21:43:27 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 28 May 2008 21:43:27 +0200 (CEST) Subject: [pypy-svn] r55369 - pypy/dist/pypy/doc Message-ID: <20080528194327.720E7169EF9@codespeak.net> Author: arigo Date: Wed May 28 21:43:25 2008 New Revision: 55369 Modified: pypy/dist/pypy/doc/cpython_differences.txt Log: Link to the blog posts (thanks cfbolz). Modified: pypy/dist/pypy/doc/cpython_differences.txt ============================================================================== --- pypy/dist/pypy/doc/cpython_differences.txt (original) +++ pypy/dist/pypy/doc/cpython_differences.txt Wed May 28 21:43:25 2008 @@ -32,7 +32,15 @@ There are a few extra implications for the difference in the GC. Most notably, if an object has a __del__, the __del__ is never called more than once in PyPy; but CPython will call the same __del__ several times -if the object is resurrected and dies again. +if the object is resurrected and dies again. The __del__ methods are +called in "the right" order if they are on objects pointing to each +other, as in CPython, but unlike CPython, if there is a dead cycle of +objects referencing each other, their __del__ methods are called anyway; +CPython would instead put them into the list ``garbage`` of the ``gc`` +module. More information is available on the blog `[1]`__ `[2]`__. + +.. __: http://morepypy.blogspot.com/2008/02/python-finalizers-semantics-part-1.html +.. __: http://morepypy.blogspot.com/2008/02/python-finalizers-semantics-part-2.html The built-in function ``id()`` returns numbers that are not addresses for most of PyPy's garbage collectors. From arigo at codespeak.net Wed May 28 22:12:22 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 28 May 2008 22:12:22 +0200 (CEST) Subject: [pypy-svn] r55375 - in pypy/dist/pypy/translator/goal: . test2 Message-ID: <20080528201222.DDE20169F3F@codespeak.net> Author: arigo Date: Wed May 28 22:12:21 2008 New Revision: 55375 Modified: pypy/dist/pypy/translator/goal/app_main.py pypy/dist/pypy/translator/goal/test2/test_app_main.py Log: issue372 testing When stdout is not a tty, use full buffering instead of line buffering. Modified: pypy/dist/pypy/translator/goal/app_main.py ============================================================================== --- pypy/dist/pypy/translator/goal/app_main.py (original) +++ pypy/dist/pypy/translator/goal/app_main.py Wed May 28 22:12:21 2008 @@ -141,6 +141,9 @@ sys.stdout = sys.__stdout__ = os.fdopen(1, 'wb', 0) sys.stderr = sys.__stderr__ = os.fdopen(2, 'wb', 0) +def set_fully_buffered_io(): + sys.stdout = sys.__stdout__ = os.fdopen(1, 'w') + # ____________________________________________________________ # Main entry point @@ -207,6 +210,7 @@ run_module = False run_stdin = False oldstyle_classes = False + unbuffered = False while i < len(argv): arg = argv[i] if not arg.startswith('-'): @@ -220,7 +224,7 @@ run_command = True break elif arg == '-u': - set_unbuffered_io() + unbuffered = True elif arg == '-O': pass elif arg == '--version': @@ -262,6 +266,12 @@ # but we need more in the translated PyPy for the compiler package sys.setrecursionlimit(5000) + if unbuffered: + set_unbuffered_io() + elif not sys.stdout.isatty(): + set_fully_buffered_io() + + mainmodule = type(sys)('__main__') sys.modules['__main__'] = mainmodule Modified: pypy/dist/pypy/translator/goal/test2/test_app_main.py ============================================================================== --- pypy/dist/pypy/translator/goal/test2/test_app_main.py (original) +++ pypy/dist/pypy/translator/goal/test2/test_app_main.py Wed May 28 22:12:21 2008 @@ -418,3 +418,22 @@ expect_prompt=True, expect_banner=False) assert 'hello world\n' in data assert '42\n' in data + + def test_non_interactive_stdout_fully_buffered(self): + path = getscript(r""" + import sys, time + sys.stdout.write('\x00(STDOUT)\n\x00') # stays in buffers + time.sleep(1) + sys.stderr.write('\x00[STDERR]\n\x00') + time.sleep(1) + # stdout flushed automatically here + """) + cmdline = '%s -u "%s" %s' % (sys.executable, app_main, path) + print 'POPEN:', cmdline + child_in, child_out_err = os.popen4(cmdline) + data = child_out_err.read(11) + assert data == '\x00[STDERR]\n\x00' # from stderr + child_in.close() + data = child_out_err.read(11) + assert data == '\x00(STDOUT)\n\x00' # from stdout + child_out_err.close() From cfbolz at codespeak.net Wed May 28 22:40:09 2008 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 28 May 2008 22:40:09 +0200 (CEST) Subject: [pypy-svn] r55376 - pypy/branch/smalltalk-shadow-changes Message-ID: <20080528204009.0A6762A80AC@codespeak.net> Author: cfbolz Date: Wed May 28 22:40:06 2008 New Revision: 55376 Removed: pypy/branch/smalltalk-shadow-changes/ Log: kill merged branch From santagada at codespeak.net Thu May 29 08:36:44 2008 From: santagada at codespeak.net (santagada at codespeak.net) Date: Thu, 29 May 2008 08:36:44 +0200 (CEST) Subject: [pypy-svn] r55379 - pypy/branch/js-refactoring/pypy/lang/js Message-ID: <20080529063644.0330A168560@codespeak.net> Author: santagada Date: Thu May 29 08:36:37 2008 New Revision: 55379 Modified: pypy/branch/js-refactoring/pypy/lang/js/interpreter.py pypy/branch/js-refactoring/pypy/lang/js/jscode.py pypy/branch/js-refactoring/pypy/lang/js/jsobj.py Log: lots of array fixes, some string hacks, promote to objects before trying to store member, print the bytecodes on the interpreter, a lot more tests are running and passing. Modified: pypy/branch/js-refactoring/pypy/lang/js/interpreter.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/interpreter.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/interpreter.py Thu May 29 08:36:37 2008 @@ -4,8 +4,9 @@ from pypy.lang.js.astbuilder import ASTBuilder from pypy.lang.js.jsobj import global_context, W_Object,\ w_Undefined, W_NewBuiltin, W_IntNumber, w_Null, create_object, W_Boolean,\ - W_FloatNumber, W_String, W_Builtin, W_Array, w_Null,\ - isnull_or_undefined, W_PrimitiveObject, W_ListObject, W_BaseNumber + W_FloatNumber, W_String, W_Builtin, W_Array, w_Null, newbool,\ + isnull_or_undefined, W_PrimitiveObject, W_ListObject, W_BaseNumber,\ + DE, DD, RO, IT from pypy.lang.js.execution import ThrowException, JsTypeError from pypy.rlib.objectmodel import we_are_translated from pypy.rlib.streamio import open_file_as_stream @@ -51,15 +52,15 @@ class W_BooleanObject(W_NativeObject): def Call(self, ctx, args=[], this=None): if len(args) >= 1 and not isnull_or_undefined(args[0]): - return W_Boolean(args[0].ToBoolean()) + return newbool(args[0].ToBoolean()) else: - return W_Boolean(False) + return newbool(False) def Construct(self, ctx, args=[]): if len(args) >= 1 and not isnull_or_undefined(args[0]): - Value = W_Boolean(args[0].ToBoolean()) + Value = newbool(args[0].ToBoolean()) return create_object(ctx, 'Boolean', Value = Value) - return create_object(ctx, 'Boolean', Value = W_Boolean(False)) + return create_object(ctx, 'Boolean', Value = newbool(False)) class W_NumberObject(W_NativeObject): def Call(self, ctx, args=[], this=None): @@ -161,17 +162,17 @@ def isnanjs(ctx, args, this): if len(args) < 1: - return W_Boolean(True) - return W_Boolean(isnan(args[0].ToNumber(ctx))) + return newbool(True) + return newbool(isnan(args[0].ToNumber(ctx))) def isfinitejs(ctx, args, this): if len(args) < 1: - return W_Boolean(True) + return newbool(True) n = args[0].ToNumber(ctx) if isinf(n) or isnan(n): - return W_Boolean(False) + return newbool(False) else: - return W_Boolean(True) + return newbool(True) def absjs(ctx, args, this): val = args[0] @@ -193,6 +194,9 @@ def versionjs(ctx, args, this): return w_Undefined +def unescapejs(ctx, args, this): + return args[0] + class W_ToString(W_NewBuiltin): def Call(self, ctx, args=[], this=None): return W_String("[object %s]"%this.Class) @@ -206,8 +210,8 @@ if len(args) >= 1: propname = args[0].ToString(ctx) if propname in this.propdict: - return W_Boolean(True) - return W_Boolean(False) + return newbool(True) + return newbool(False) class W_IsPrototypeOf(W_NewBuiltin): def Call(self, ctx, args=[], this=None): @@ -216,17 +220,17 @@ V = args[0].Prototype while V is not None: if O == V: - return W_Boolean(True) + return newbool(True) V = V.Prototype - return W_Boolean(False) + return newbool(False) class W_PropertyIsEnumerable(W_NewBuiltin): def Call(self, ctx, args=[], this=None): if len(args) >= 1: propname = args[0].ToString(ctx) if propname in this.propdict and not this.propdict[propname].de: - return W_Boolean(True) - return W_Boolean(False) + return newbool(True) + return newbool(False) class W_Function(W_NewBuiltin): def Call(self, ctx, args=[], this=None): @@ -322,7 +326,7 @@ raise JsTypeError('%s.prototype.valueOf called with incompatible type' % self.type()) return this.Value return W_ValueValueOf(ctx) - + class W_CharAt(W_NewBuiltin): def Call(self, ctx, args=[], this=None): string = this.ToString(ctx) @@ -419,7 +423,8 @@ def put_values(obj, dictvalues): for key,value in dictvalues.iteritems(): obj.Put(ctx, key, value) - + + allon = DE | DD | RO w_Global = W_Object(Class="global") ctx = global_context(w_Global) @@ -432,14 +437,14 @@ w_Global.Put(ctx, 'Function', w_Function) w_Object = W_ObjectObject('Object', w_Function) - w_Object.Put(ctx, 'prototype', w_ObjPrototype, dd=True, de=True, ro=True) + w_Object.Put(ctx, 'prototype', w_ObjPrototype, flags = allon) w_Global.Put(ctx, 'Object', w_Object) w_FncPrototype = w_Function.Call(ctx, this=w_Function) - w_Function.Put(ctx, 'prototype', w_FncPrototype, dd=True, de=True, ro=True) + w_Function.Put(ctx, 'prototype', w_FncPrototype, flags = allon) w_Function.Put(ctx, 'constructor', w_Function) - w_Object.Put(ctx, 'length', W_IntNumber(1), ro=True, dd=True) + w_Object.Put(ctx, 'length', W_IntNumber(1), flags = RO | DD) toString = W_ToString(ctx) @@ -464,10 +469,10 @@ }) w_Boolean = W_BooleanObject('Boolean', w_FncPrototype) - w_Boolean.Put(ctx, 'constructor', w_FncPrototype, dd=True, ro=True, de=True) - w_Boolean.Put(ctx, 'length', W_IntNumber(1), dd=True, ro=True, de=True) + w_Boolean.Put(ctx, 'constructor', w_FncPrototype, flags = allon) + w_Boolean.Put(ctx, 'length', W_IntNumber(1), flags = allon) - w_BoolPrototype = create_object(ctx, 'Object', Value=W_Boolean(False)) + w_BoolPrototype = create_object(ctx, 'Object', Value=newbool(False)) w_BoolPrototype.Class = 'Boolean' put_values(w_BoolPrototype, { @@ -477,7 +482,7 @@ 'valueOf': get_value_of('Boolean', ctx), }) - w_Boolean.Put(ctx, 'prototype', w_BoolPrototype, dd=True, ro=True, de=True) + w_Boolean.Put(ctx, 'prototype', w_BoolPrototype, flags = allon) w_Global.Put(ctx, 'Boolean', w_Boolean) @@ -501,16 +506,13 @@ '__proto__': w_empty_fun, 'length' : W_IntNumber(1), }) - w_Number.propdict['prototype'].ro = True - w_Number.Put(ctx, 'MAX_VALUE', W_FloatNumber(1.7976931348623157e308), - ro=True, dd=True) - w_Number.Put(ctx, 'MIN_VALUE', W_FloatNumber(0), ro=True, dd=True) - w_Number.Put(ctx, 'NaN', W_FloatNumber(NAN), ro=True, dd=True) + w_Number.propdict['prototype'].flags |= RO + w_Number.Put(ctx, 'MAX_VALUE', W_FloatNumber(1.7976931348623157e308), flags = RO|DD) + w_Number.Put(ctx, 'MIN_VALUE', W_FloatNumber(0), flags = RO|DD) + w_Number.Put(ctx, 'NaN', W_FloatNumber(NAN), flags = RO|DD) # ^^^ this is exactly in test case suite - w_Number.Put(ctx, 'POSITIVE_INFINITY', W_FloatNumber(INFINITY), - ro=True, dd=True) - w_Number.Put(ctx, 'NEGATIVE_INFINITY', W_FloatNumber(-INFINITY), - ro=True, dd=True) + w_Number.Put(ctx, 'POSITIVE_INFINITY', W_FloatNumber(INFINITY), flags = RO|DD) + w_Number.Put(ctx, 'NEGATIVE_INFINITY', W_FloatNumber(-INFINITY), flags = RO|DD) w_Global.Put(ctx, 'Number', w_Number) @@ -538,16 +540,19 @@ w_Array = W_ArrayObject('Array', w_FncPrototype) - w_ArrPrototype = create_object(ctx, 'Object') - w_ArrPrototype.Class = 'Array' + w_ArrPrototype = W_Array(Prototype=w_ObjPrototype) put_values(w_ArrPrototype, { 'constructor': w_FncPrototype, '__proto__': w_ArrPrototype, 'toString': W_ArrayToString(ctx), + 'join': W_ArrayJoin(ctx) }) - w_Array.Put(ctx, 'prototype', w_ArrPrototype) + w_Array.Put(ctx, 'prototype', w_ArrPrototype, flags = allon) + w_Array.Put(ctx, '__proto__', w_FncPrototype, flags = allon) + w_Array.Put(ctx, 'length', W_IntNumber(1), flags = allon) + w_Global.Put(ctx, 'Array', w_Array) @@ -555,7 +560,7 @@ w_math = W_Object(Class='Math') w_Global.Put(ctx, 'Math', w_math) w_math.Put(ctx, '__proto__', w_ObjPrototype) - w_math.Put(ctx, 'prototype', w_ObjPrototype, dd=True, de=True, ro=True) + w_math.Put(ctx, 'prototype', w_ObjPrototype, flags = allon) w_math.Put(ctx, 'abs', W_Builtin(absjs, Class='function')) w_math.Put(ctx, 'floor', W_Builtin(floorjs, Class='function')) w_math.Put(ctx, 'pow', W_Builtin(powjs, Class='function')) @@ -577,8 +582,9 @@ w_Global.Put(ctx, 'parseFloat', W_Builtin(parseFloatjs)) w_Global.Put(ctx, 'isNaN', W_Builtin(isnanjs)) w_Global.Put(ctx, 'isFinite', W_Builtin(isfinitejs)) - w_Global.Put(ctx, 'print', W_Builtin(printjs)) + w_Global.Put(ctx, 'unescape', W_Builtin(unescapejs)) + w_Global.Put(ctx, 'this', w_Global) # DEBUGGING @@ -597,6 +603,7 @@ # debugging self._code = bytecode if interactive: + print bytecode return bytecode.run(self.global_context, retlast=True) else: bytecode.run(self.global_context) @@ -614,7 +621,7 @@ elif isinstance(arg, float): res.append(W_FloatNumber(arg)) elif isinstance(arg, bool): - res.append(W_Boolean(arg)) + res.append(newbool(arg)) else: raise Exception("Cannot wrap %s" % (arg,)) return res Modified: pypy/branch/js-refactoring/pypy/lang/js/jscode.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/jscode.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/jscode.py Thu May 29 08:36:37 2008 @@ -2,7 +2,8 @@ from pypy.lang.js.jsobj import W_IntNumber, W_FloatNumber, W_String,\ W_Array, W_PrimitiveObject, ActivationObject,\ create_object, W_Object, w_Undefined, newbool,\ - w_True, w_False, W_List, w_Null, W_Iterator, W_Root + w_True, w_False, W_List, w_Null, W_Iterator, W_Root,\ + DD, DE, RO from pypy.lang.js.execution import JsTypeError, ReturnException, ThrowException from pypy.rlib.unroll import unrolling_iterable from pypy.lang.js.baseop import plus, sub, compare, AbstractEC, StrictEC,\ @@ -330,7 +331,7 @@ callfunc=self.funcobj) w_func.Put(ctx, 'length', W_IntNumber(len(self.funcobj.params))) w_obj = create_object(ctx, 'Object') - w_obj.Put(ctx, 'constructor', w_func, de=True) + w_obj.Put(ctx, 'constructor', w_func, flags = DE) w_func.Put(ctx, 'prototype', w_obj) stack.append(w_func) @@ -542,7 +543,7 @@ value = stack.pop() name = elem.ToString() value = self.operation(ctx, left, name, value) - left.Put(ctx, name, value) + left.ToObject(ctx).Put(ctx, name, value) stack.append(value) class STORE_MEMBER(BaseStoreMember): @@ -709,7 +710,7 @@ w_func = W_Object(ctx=ctx, Prototype=proto, Class='Function', callfunc=self.funcobj) w_func.Put(ctx, 'length', W_IntNumber(len(self.funcobj.params))) w_obj = create_object(ctx, 'Object') - w_obj.Put(ctx, 'constructor', w_func, de=True) + w_obj.Put(ctx, 'constructor', w_func, flags = DE) w_func.Put(ctx, 'prototype', w_obj) if self.funcobj.name is not None: ctx.Put(ctx, self.funcobj.name, w_func) @@ -728,7 +729,7 @@ self.name = name def eval(self, ctx, stack): - ctx.Put(ctx, self.name, w_Undefined, dd=True) + ctx.Put(ctx, self.name, w_Undefined, flags = DD) def __repr__(self): return 'DECLARE_VAR "%s"' % (self.name,) @@ -829,7 +830,7 @@ class LOAD_ITERATOR(Opcode): def eval(self, ctx, stack): obj = stack.pop().ToObject(ctx) - props = [prop.value for prop in obj.propdict.values() if not prop.de] + props = [prop.value for prop in obj.propdict.values() if not prop.flags & DE] stack.append(W_Iterator(props)) class JUMP_IF_ITERATOR_EMPTY(BaseJump): @@ -883,7 +884,7 @@ OpcodeMap = {} for name, value in locals().items(): - if name.upper() == name and issubclass(value, Opcode): + if name.upper() == name and type(value) == type(Opcode) and issubclass(value, Opcode): OpcodeMap[name] = value opcode_unrolling = unrolling_iterable(OpcodeMap.items()) Modified: pypy/branch/js-refactoring/pypy/lang/js/jsobj.py ============================================================================== --- pypy/branch/js-refactoring/pypy/lang/js/jsobj.py (original) +++ pypy/branch/js-refactoring/pypy/lang/js/jsobj.py Thu May 29 08:36:37 2008 @@ -4,22 +4,22 @@ from pypy.lang.js.execution import ThrowException, JsTypeError,\ RangeError, ReturnException +DE = 1 +DD = 2 +RO = 4 +IT = 8 + class SeePage(NotImplementedError): pass class Property(object): - def __init__(self, name, value, dd=False, - ro=False, de=False, it=False): + def __init__(self, name, value, flags = 0): self.name = name self.value = value - self.dd = dd - self.ro = ro - self.de = de - self.it = it - + self.flags = flags + def __repr__(self): - return "|%s %d%d%d|"%(self.value, self.dd, - self.ro, self.de) + return "|%s : %s %d|"%(self.name, self.value, self.flags) def internal_property(name, value): """return a internal property with the right attributes""" @@ -54,8 +54,7 @@ def Get(self, ctx, P): raise NotImplementedError() - def Put(self, ctx, P, V, dd=False, - ro=False, de=False, it=False): + def Put(self, ctx, P, V, flags = 0): raise NotImplementedError() def PutValue(self, w, ctx): @@ -113,8 +112,7 @@ self.Prototype = Prototype if Prototype is None: Prototype = w_Undefined - self.propdict['prototype'] = Property('prototype', Prototype, - dd=True, de=True) + self.propdict['prototype'] = Property('prototype', Prototype, flags = DE|DD) self.Class = Class self.callfunc = callfunc if callfunc is not None: @@ -166,21 +164,20 @@ def CanPut(self, P): if P in self.propdict: - if self.propdict[P].ro: return False + if self.propdict[P].flags & RO: return False return True if self.Prototype is None: return True return self.Prototype.CanPut(P) - def Put(self, ctx, P, V, dd=False, - ro=False, de=False, it=False): - try: - P = self.propdict[P] - if P.ro: - return - P.value = V - except KeyError: - self.propdict[P] = Property(P, V, - dd = dd, ro = ro, de = de, it = it) + def Put(self, ctx, P, V, flags = 0): + + if not self.CanPut(P): return + if P in self.propdict: + prop = self.propdict[P] + prop.value = V + prop.flags |= flags + else: + self.propdict[P] = Property(P, V, flags = flags) def HasProperty(self, P): if P in self.propdict: return True @@ -189,7 +186,8 @@ def Delete(self, P): if P in self.propdict: - if self.propdict[P].dd: return False + if self.propdict[P].flags & DD: + return False del self.propdict[P] return True return True @@ -235,7 +233,7 @@ return 'object' -class W_Primitive(W_PrimitiveObject): +class W_Primitive(W_Root): """unifying parent for primitives""" def ToPrimitive(self, ctx, hint=""): return self @@ -315,8 +313,8 @@ class W_Array(W_ListObject): def __init__(self, ctx=None, Prototype=None, Class='Array', Value=w_Undefined, callfunc=None): - W_PrimitiveObject.__init__(self, ctx, Prototype, Class, Value, callfunc) - self.Put(ctx, 'length', W_IntNumber(0)) + super(W_Array, self).__init__(ctx, Prototype, Class, Value, callfunc) + self.Put(ctx, 'length', W_IntNumber(0), flags = DD) self.length = r_uint(0) def set_length(self, newlength): @@ -331,11 +329,10 @@ self.length = newlength self.propdict['length'].value = W_FloatNumber(newlength) - def Put(self, ctx, P, V, dd=False, - ro=False, de=False, it=False): + def Put(self, ctx, P, V, flags = 0): if not self.CanPut(P): return if not P in self.propdict: - self.propdict[P] = Property(P, V, dd = dd, ro = ro, de = de, it = it) + self.propdict[P] = Property(P, V, flags = flags) else: if P != 'length': self.propdict[P].value = V @@ -361,7 +358,7 @@ class W_Boolean(W_Primitive): def __init__(self, boolval): - super(W_Primitive, self).__init__() + super(W_Boolean, self).__init__() self.boolval = bool(boolval) def ToObject(self, ctx): @@ -388,14 +385,21 @@ class W_String(W_Primitive): def __init__(self, strval): - super(W_Primitive, self).__init__() + super(W_String, self).__init__() self.strval = strval def __repr__(self): return 'W_String(%s)' % (self.strval,) + def Get(self, ctx, P): #as hackinsh as can get + if P == 'length': + return W_FloatNumber(len(self.strval)) + else: + proto = ctx.get_global().Get(ctx, 'String').Get(ctx, 'prototype') + return proto.Get(ctx, P) + def ToObject(self, ctx): - return create_object(ctx, 'String', Value=self) + return self #create_object(ctx, 'String', Value=self) def ToString(self, ctx=None): return self.strval @@ -427,7 +431,7 @@ def ToObject(self, ctx): return create_object(ctx, 'Number', Value=self) - def Get(self, ctx, name): + def Get(self, ctx, P): return w_Undefined def type(self): @@ -437,7 +441,7 @@ """ Number known to be an integer """ def __init__(self, intval): - super(W_Primitive, self).__init__() + super(W_IntNumber, self).__init__() self.intval = intmask(intval) def ToString(self, ctx=None): @@ -467,7 +471,7 @@ """ Number known to be a float """ def __init__(self, floatval): - super(W_Primitive, self).__init__() + super(W_FloatNumber, self).__init__() self.floatval = float(floatval) def ToString(self, ctx = None): @@ -480,9 +484,13 @@ else: return '-Infinity' try: - return str(ovfcheck_float_to_int(self.floatval)) + intval = ovfcheck_float_to_int(self.floatval) + if intval == self.floatval: + return str(intval) except OverflowError: - return str(self.floatval) + pass + + return str(self.floatval) def ToBoolean(self): if isnan(self.floatval): @@ -553,7 +561,7 @@ assert isinstance(obj, W_PrimitiveObject) try: P = obj.propdict[name] - if P.ro: + if P.flags & RO: return P.value = value return @@ -567,7 +575,7 @@ assert isinstance(obj, W_PrimitiveObject) try: P = obj.propdict[name] - if P.dd: + if P.flags & DD: return False del obj.propdict[name] return True @@ -575,9 +583,9 @@ pass return False - def Put(self, ctx, name, value, dd=False): + def Put(self, ctx, name, value, flags = 0): assert name is not None - self.variable.Put(ctx, name, value, dd=dd) + self.variable.Put(ctx, name, value, flags = flags) def get_global(self): return self.scope[-1] @@ -607,14 +615,14 @@ ctx = ExecutionContext([w_global], this = w_global, variable = w_global, - jsproperty = Property('', w_Undefined, dd=True)) + jsproperty = Property('', w_Undefined, flags = DD)) return ctx def function_context(scope, activation, this=None): newscope = scope[:] ctx = ExecutionContext(newscope, this = this, - jsproperty = Property('', w_Undefined, dd=True)) + jsproperty = Property('', w_Undefined, flags = DD)) ctx.push_object(activation) return ctx From arigo at codespeak.net Thu May 29 10:02:42 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 29 May 2008 10:02:42 +0200 (CEST) Subject: [pypy-svn] r55381 - pypy/dist/pypy/translator/goal Message-ID: <20080529080242.5A16916854B@codespeak.net> Author: arigo Date: Thu May 29 10:02:40 2008 New Revision: 55381 Modified: pypy/dist/pypy/translator/goal/bench-cronjob.py Log: Update the list of pypy-c's built by tuatara. Modified: pypy/dist/pypy/translator/goal/bench-cronjob.py ============================================================================== --- pypy/dist/pypy/translator/goal/bench-cronjob.py (original) +++ pypy/dist/pypy/translator/goal/bench-cronjob.py Thu May 29 10:02:40 2008 @@ -183,12 +183,10 @@ c c--stackless--_faassen c--_faassen--_allworkingmodules - c--thread - c--gc=marksweep--_faassen + c--thread--gc=hybrid--_faassen c--gc=semispace--_faassen c--gc=generation--_faassen c--gc=hybrid--_faassen - c--_objspace-std-withrope cli--_faassen jvm--_faassen """.split('\n') if backend.strip() and not backend.strip().startswith('#')] From arigo at codespeak.net Thu May 29 14:01:15 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 29 May 2008 14:01:15 +0200 (CEST) Subject: [pypy-svn] r55388 - in pypy/dist/pypy/translator: c tool Message-ID: <20080529120115.5C91A168504@codespeak.net> Author: arigo Date: Thu May 29 14:01:10 2008 New Revision: 55388 Modified: pypy/dist/pypy/translator/c/genc.py pypy/dist/pypy/translator/tool/cbuild.py Log: - handling config.translation.profopt is a bit messy - try a workaround for a gcc profile bug Modified: pypy/dist/pypy/translator/c/genc.py ============================================================================== --- pypy/dist/pypy/translator/c/genc.py (original) +++ pypy/dist/pypy/translator/c/genc.py Thu May 29 14:01:10 2008 @@ -288,22 +288,32 @@ standalone = True executable_name = None - def getentrypointptr(self): - # XXX check that the entrypoint has the correct - # signature: list-of-strings -> int - bk = self.translator.annotator.bookkeeper - return getfunctionptr(bk.getdesc(self.entrypoint).getuniquegraph()) - - def getccompiler(self): - cc = self.config.translation.cc + def getprofbased(self): profbased = None if self.config.translation.instrumentctl is not None: profbased = self.config.translation.instrumentctl else: + # xxx handling config.translation.profopt is a bit messy, because + # it could be an empty string (not to be confused with None) and + # because noprofopt can be used as an override. profopt = self.config.translation.profopt if profopt is not None and not self.config.translation.noprofopt: profbased = (ProfOpt, profopt) + return profbased + + def has_profopt(self): + profbased = self.getprofbased() + return (profbased and isinstance(profbased, tuple) + and profbased[0] is ProfOpt) + def getentrypointptr(self): + # XXX check that the entrypoint has the correct + # signature: list-of-strings -> int + bk = self.translator.annotator.bookkeeper + return getfunctionptr(bk.getdesc(self.entrypoint).getuniquegraph()) + + def getccompiler(self): + cc = self.config.translation.cc # Copy extrafiles to target directory, if needed extrafiles = [] for fn in self.extrafiles: @@ -316,7 +326,7 @@ return CCompiler( [self.c_source_filename] + extrafiles, - self.eci, compiler_exe = cc, profbased = profbased) + self.eci, compiler_exe = cc, profbased = self.getprofbased()) def compile(self): assert self.c_source_filename @@ -389,7 +399,7 @@ cc = self.config.translation.cc else: cc = 'gcc' - if self.config.translation.profopt: + if self.has_profopt(): profopt = self.config.translation.profopt default_target = 'profopt' else: @@ -855,11 +865,14 @@ $(TARGET): $(OBJECTS) \t$(CC) $(LDFLAGS) $(TFLAGS) -o $@ $(OBJECTS) $(LIBDIRS) $(LIBS) +# -frandom-seed is an attempted workaround for a gcc bug with -fprofile-* +# (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=20815) + %.o: %.c -\t$(CC) $(CFLAGS) -o $@ -c $< $(INCLUDEDIRS) +\t$(CC) $(CFLAGS) -frandom-seed=$< -o $@ -c $< $(INCLUDEDIRS) %.s: %.c -\t$(CC) $(CFLAGS) -o $@ -S $< $(INCLUDEDIRS) +\t$(CC) $(CFLAGS) -frandom-seed=$< -o $@ -S $< $(INCLUDEDIRS) %.gcmap: %.s \t$(PYPYDIR)/translator/c/gcc/trackgcroot.py -t $< > $@ || (rm -f $@ && exit 1) @@ -868,7 +881,7 @@ \t$(PYPYDIR)/translator/c/gcc/trackgcroot.py $(GCMAPFILES) > $@ || (rm -f $@ && exit 1) clean: -\trm -f $(OBJECTS) $(TARGET) $(GCMAPFILES) *.gc?? +\trm -f $(OBJECTS) $(TARGET) $(GCMAPFILES) ../*/*.gc?? clean_noprof: \trm -f $(OBJECTS) $(TARGET) $(GCMAPFILES) Modified: pypy/dist/pypy/translator/tool/cbuild.py ============================================================================== --- pypy/dist/pypy/translator/tool/cbuild.py (original) +++ pypy/dist/pypy/translator/tool/cbuild.py Thu May 29 14:01:10 2008 @@ -467,6 +467,7 @@ def build(self, option): compiler = self.compiler + compiler.fix_gcc_random_seed = True compiler.compile_extra.append(option) compiler.link_extra.append(option) try: @@ -479,6 +480,7 @@ pass class CCompiler: + fix_gcc_random_seed = False def __init__(self, cfilenames, eci, outputfilename=None, compiler_exe=None, profbased=None): @@ -575,11 +577,16 @@ objects = [] for cfile in self.cfilenames: cfile = py.path.local(cfile) + compile_extra = self.compile_extra[:] + # -frandom-seed is an attempted workaround for a bug with + # -fprofile-generate and -fprofile-use + if self.fix_gcc_random_seed: + compile_extra.append('-frandom-seed=%s' % (cfile.basename,)) old = cfile.dirpath().chdir() try: res = compiler.compile([cfile.basename], include_dirs=self.eci.include_dirs, - extra_preargs=self.compile_extra) + extra_preargs=compile_extra) assert len(res) == 1 cobjfile = py.path.local(res[0]) assert cobjfile.check() From pedronis at codespeak.net Thu May 29 14:26:47 2008 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 29 May 2008 14:26:47 +0200 (CEST) Subject: [pypy-svn] r55389 - pypy/django/tests Message-ID: <20080529122647.0E476168518@codespeak.net> Author: pedronis Date: Thu May 29 14:26:47 2008 New Revision: 55389 Modified: pypy/django/tests/conftest.py Log: mostly trying to reduce my own confusion: this makes more tests pass under the py.test + cpython2.5 + pysqlite-ctypes combination Modified: pypy/django/tests/conftest.py ============================================================================== --- pypy/django/tests/conftest.py (original) +++ pypy/django/tests/conftest.py Thu May 29 14:26:47 2008 @@ -20,6 +20,23 @@ import unittest +def setup_and_run(func, *args, **kwds): + from django.test.utils import setup_test_environment, teardown_test_environment + from django.test.utils import create_test_db, destroy_test_db + from django.conf import settings + old_name = settings.DATABASE_NAME + setup_test_environment() + create_test_db(0) + try: + func(*args, **kwds) + finally: + destroy_test_db(old_name, 0) + teardown_test_environment() + # manually clear some global state, as there is not API to do this :-( + from django.core import management + management._commands = None + + class DocTestItem(py.test.collect.Item): def __init__(self, name, mod, docstr): @@ -29,20 +46,7 @@ self.mod = mod def run(self): - from django.test.utils import setup_test_environment, teardown_test_environment - from django.test.utils import create_test_db, destroy_test_db - from django.conf import settings - old_name = settings.DATABASE_NAME - setup_test_environment() - create_test_db(0) - try: - self.execute(self.mod, self.docstr) - finally: - destroy_test_db(old_name, 0) - teardown_test_environment() - # manually clear some global state, as there is not API to do this :-( - from django.core import management - management._commands = None + setup_and_run(self.execute, self.mod, self.docstr) def execute(self, mod, docstring): from django.test.testcases import OutputChecker, DocTestRunner @@ -185,7 +189,7 @@ assert len(names) == 2 testcasecls = getattr(mod, names[0]) testcase = testcasecls(names[1]) - run_testcase_method(testcase) + setup_and_run(run_testcase_method, testcase) class DjangoTestDirectory(py.test.collect.Directory): def _level(self): @@ -299,7 +303,7 @@ def run_testcase_method(method): result = method.defaultTestResult() - method.run(result) + method(result) # ! django overrides __call__ so calling run is not enough if result.errors: assert len(result.errors) print result.errors[0][1] From antocuni at codespeak.net Thu May 29 14:41:19 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 29 May 2008 14:41:19 +0200 (CEST) Subject: [pypy-svn] r55390 - pypy/django/django/core/management/commands Message-ID: <20080529124119.783DE168529@codespeak.net> Author: antocuni Date: Thu May 29 14:41:16 2008 New Revision: 55390 Modified: pypy/django/django/core/management/commands/syncdb.py Log: be a little more strict when checking the error message Modified: pypy/django/django/core/management/commands/syncdb.py ============================================================================== --- pypy/django/django/core/management/commands/syncdb.py (original) +++ pypy/django/django/core/management/commands/syncdb.py Thu May 29 14:41:16 2008 @@ -34,8 +34,8 @@ try: __import__(app_name + '.management', {}, {}, ['']) except ImportError, exc: - if 'management' not in exc.args[0]: - #if not exc.args[0].startswith('No module named management'): + msg = exc.args[0] + if not msg.startswith('No module named') or 'management' not in msg: raise cursor = connection.cursor() From antocuni at codespeak.net Thu May 29 14:42:07 2008 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 29 May 2008 14:42:07 +0200 (CEST) Subject: [pypy-svn] r55391 - pypy/django/tests Message-ID: <20080529124207.A1AA316852F@codespeak.net> Author: antocuni Date: Thu May 29 14:42:05 2008 New Revision: 55391 Modified: pypy/django/tests/failures.txt Log: update Modified: pypy/django/tests/failures.txt ============================================================================== --- pypy/django/tests/failures.txt (original) +++ pypy/django/tests/failures.txt Thu May 29 14:42:05 2008 @@ -26,10 +26,6 @@ regressiontests.dispatch.tests.test_dispatcher.DispatcherTests - garbage collection not happening immediately -doctest regressiontests.datastructures.tests[45] - dict subclasses - -regressiontests.httpwrappers.tests - dict subclasses - Other tests ----------- @@ -37,7 +33,9 @@ "some tests" fixed in r54740 (XXX: which are "some tests") -regressiontests/datastructures fixed in r55068 +regressiontests/datastructures fixed by r55068, r55159 and r55301 + +regressiontests.httpwrappers.tests fixed by r55301 regressiontests/forms/widget_tests and others fixed in r55075 From arigo at codespeak.net Thu May 29 14:55:54 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 29 May 2008 14:55:54 +0200 (CEST) Subject: [pypy-svn] r55393 - pypy/dist/pypy/translator/c Message-ID: <20080529125554.0D428168515@codespeak.net> Author: arigo Date: Thu May 29 14:55:53 2008 New Revision: 55393 Modified: pypy/dist/pypy/translator/c/genc.py Log: Bah, this didn't fix the gcc profile bug, which I can reproduce with a tiny C program using fork(). For now let's keep -frandom-seed anyway as a "can't hurt" way to make compilation more reproducible. Modified: pypy/dist/pypy/translator/c/genc.py ============================================================================== --- pypy/dist/pypy/translator/c/genc.py (original) +++ pypy/dist/pypy/translator/c/genc.py Thu May 29 14:55:53 2008 @@ -865,8 +865,7 @@ $(TARGET): $(OBJECTS) \t$(CC) $(LDFLAGS) $(TFLAGS) -o $@ $(OBJECTS) $(LIBDIRS) $(LIBS) -# -frandom-seed is an attempted workaround for a gcc bug with -fprofile-* -# (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=20815) +# -frandom-seed is only to try to be as reproducable as possible %.o: %.c \t$(CC) $(CFLAGS) -frandom-seed=$< -o $@ -c $< $(INCLUDEDIRS) From arigo at codespeak.net Thu May 29 15:35:23 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 29 May 2008 15:35:23 +0200 (CEST) Subject: [pypy-svn] r55394 - in pypy/dist/pypy: rlib rlib/rstruct rpython/lltypesystem rpython/module rpython/tool rpython/tool/test translator/tool translator/tool/test Message-ID: <20080529133523.68A54168525@codespeak.net> Author: arigo Date: Thu May 29 15:35:20 2008 New Revision: 55394 Modified: pypy/dist/pypy/rlib/_rsocket_rffi.py pypy/dist/pypy/rlib/libffi.py pypy/dist/pypy/rlib/rmmap.py pypy/dist/pypy/rlib/rstruct/nativefmttable.py pypy/dist/pypy/rpython/lltypesystem/rffi.py pypy/dist/pypy/rpython/module/ll_os.py pypy/dist/pypy/rpython/module/ll_os_stat.py pypy/dist/pypy/rpython/tool/rffi_platform.py pypy/dist/pypy/rpython/tool/test/test_rffi_platform.py pypy/dist/pypy/translator/tool/cbuild.py pypy/dist/pypy/translator/tool/test/test_cbuild.py Log: Rename "pre/post_include_lines" to "pre/post_include_bits". This is now supposed to be not a list of lines, but a list of pieces of source. Duplicate pieces are removed. Should fix the fact that in a pypy-c translation each module_#.c contains dozens of copies of the same declarations... Modified: pypy/dist/pypy/rlib/_rsocket_rffi.py ============================================================================== --- pypy/dist/pypy/rlib/_rsocket_rffi.py (original) +++ pypy/dist/pypy/rlib/_rsocket_rffi.py Thu May 29 15:35:20 2008 @@ -53,7 +53,7 @@ constants = {} eci = ExternalCompilationInfo( - pre_include_lines = (HEADER + COND_HEADER).split("\n"), + post_include_bits = [HEADER, COND_HEADER], includes = includes, libraries = libraries, ) Modified: pypy/dist/pypy/rlib/libffi.py ============================================================================== --- pypy/dist/pypy/rlib/libffi.py (original) +++ pypy/dist/pypy/rlib/libffi.py Thu May 29 15:35:20 2008 @@ -37,7 +37,7 @@ else: libffidir = py.path.local(pypydir).join('translator', 'c', 'src', 'libffi_msvc') eci = ExternalCompilationInfo( - pre_include_lines = ['#define _WIN32_WINNT 0x501'], + pre_include_bits = ['#define _WIN32_WINNT 0x501'], includes = ['ffi.h', 'windows.h'], libraries = ['kernel32'], include_dirs = [libffidir], Modified: pypy/dist/pypy/rlib/rmmap.py ============================================================================== --- pypy/dist/pypy/rlib/rmmap.py (original) +++ pypy/dist/pypy/rlib/rmmap.py Thu May 29 15:35:20 2008 @@ -31,9 +31,9 @@ class CConfig: _compilation_info_ = ExternalCompilationInfo( includes=includes, - pre_include_lines=['#ifndef _GNU_SOURCE', - '#define _GNU_SOURCE', - '#endif'] + pre_include_bits=['#ifndef _GNU_SOURCE\n' + + '#define _GNU_SOURCE\n' + + '#endif'] ) size_t = rffi_platform.SimpleType("size_t", rffi.LONG) off_t = rffi_platform.SimpleType("off_t", rffi.LONG) Modified: pypy/dist/pypy/rlib/rstruct/nativefmttable.py ============================================================================== --- pypy/dist/pypy/rlib/rstruct/nativefmttable.py (original) +++ pypy/dist/pypy/rlib/rstruct/nativefmttable.py Thu May 29 15:35:20 2008 @@ -79,18 +79,18 @@ 'd': 'double', } - pre_include_lines = [] + pre_include_bits = [] for fmtchar, ctype in INSPECT.items(): - pre_include_lines += (""" + pre_include_bits.append(""" struct about_%s { char pad; %s field; }; - """ % (fmtchar, ctype)).split("\n") + """ % (fmtchar, ctype)) class CConfig: _compilation_info_ = ExternalCompilationInfo( - pre_include_lines = pre_include_lines + pre_include_bits = pre_include_bits ) for fmtchar, ctype in INSPECT.items(): Modified: pypy/dist/pypy/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rffi.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rffi.py Thu May 29 15:35:20 2008 @@ -425,7 +425,7 @@ sources = ('\n'.join(lines),) new_eci = eci.merge(ExternalCompilationInfo( separate_module_sources = sources, - post_include_lines = [getter_prototype, setter_prototype], + post_include_bits = [getter_prototype, setter_prototype], export_symbols = [getter_name, setter_name], )) Modified: pypy/dist/pypy/rpython/module/ll_os.py ============================================================================== --- pypy/dist/pypy/rpython/module/ll_os.py (original) +++ pypy/dist/pypy/rpython/module/ll_os.py Thu May 29 15:35:20 2008 @@ -97,14 +97,13 @@ defs = [] for name in self.w_star: data = {'ret_type': 'int', 'name': name} - decls.append(decl_snippet % data) - defs.append(def_snippet % data) - h_source = decls + defs + decls.append((decl_snippet % data).strip()) + defs.append((def_snippet % data).strip()) self.compilation_info = self.compilation_info.merge( ExternalCompilationInfo( - post_include_lines = decls, - separate_module_sources = ["\n".join(h_source)] + post_include_bits = decls, + separate_module_sources = ["\n".join(defs)] )) # a simple, yet usefull factory Modified: pypy/dist/pypy/rpython/module/ll_os_stat.py ============================================================================== --- pypy/dist/pypy/rpython/module/ll_os_stat.py (original) +++ pypy/dist/pypy/rpython/module/ll_os_stat.py Thu May 29 15:35:20 2008 @@ -146,7 +146,7 @@ INCLUDES = ['sys/types.h', 'sys/stat.h', 'unistd.h'] compilation_info = ExternalCompilationInfo( - pre_include_lines = ['#define _FILE_OFFSET_BITS 64'], + pre_include_bits = ['#define _FILE_OFFSET_BITS 64'], includes = INCLUDES ) Modified: pypy/dist/pypy/rpython/tool/rffi_platform.py ============================================================================== --- pypy/dist/pypy/rpython/tool/rffi_platform.py (original) +++ pypy/dist/pypy/rpython/tool/rffi_platform.py Thu May 29 15:35:20 2008 @@ -16,7 +16,7 @@ def eci_from_header(c_header_source): return ExternalCompilationInfo( - pre_include_lines=c_header_source.split("\n") + pre_include_bits=[c_header_source] ) def getstruct(name, c_header_source, interesting_fields): Modified: pypy/dist/pypy/rpython/tool/test/test_rffi_platform.py ============================================================================== --- pypy/dist/pypy/rpython/tool/test/test_rffi_platform.py (original) +++ pypy/dist/pypy/rpython/tool/test/test_rffi_platform.py Thu May 29 15:35:20 2008 @@ -111,9 +111,9 @@ class CConfig: _compilation_info_ = ExternalCompilationInfo( - pre_include_lines = ["/* a C comment */", - "#include ", - "#include "], + pre_include_bits = ["/* a C comment */", + "#include ", + "#include "], include_dirs = [str(udir)] ) @@ -130,13 +130,15 @@ def test_ifdef(): class CConfig: _compilation_info_ = ExternalCompilationInfo( - post_include_lines = ['/* a C comment */', - '#define XYZZY 42', - 'typedef int foo;', - 'struct s {', - 'int i;', - 'double f;' - '};']) + post_include_bits = ['/* a C comment */', + '#define XYZZY 42', + 'typedef int foo;', + ''' + struct s { + int i; + double f; + }; + ''']) s = rffi_platform.Struct('struct s', [('i', rffi.INT)], ifdef='XYZZY') @@ -155,7 +157,7 @@ def test_nested_structs(): class CConfig: _compilation_info_ = ExternalCompilationInfo( - post_include_lines=""" + post_include_bits=[""" struct x { int foo; unsigned long bar; @@ -164,7 +166,7 @@ char c; struct x x; }; - """.split("\n")) + """]) x = rffi_platform.Struct("struct x", [("bar", rffi.SHORT)]) y = rffi_platform.Struct("struct y", [("x", x)]) @@ -178,7 +180,7 @@ def test_nested_structs_in_the_opposite_order(): class CConfig: _compilation_info_ = ExternalCompilationInfo( - post_include_lines=""" + post_include_bits=[""" struct y { int foo; unsigned long bar; @@ -187,7 +189,7 @@ char c; struct y y; }; - """.split("\n")) + """]) y = rffi_platform.Struct("struct y", [("bar", rffi.SHORT)]) x = rffi_platform.Struct("struct x", [("y", y)]) Modified: pypy/dist/pypy/translator/tool/cbuild.py ============================================================================== --- pypy/dist/pypy/translator/tool/cbuild.py (original) +++ pypy/dist/pypy/translator/tool/cbuild.py Thu May 29 15:35:20 2008 @@ -14,18 +14,17 @@ class ExternalCompilationInfo(object): - _ATTRIBUTES = ['pre_include_lines', 'includes', 'include_dirs', - 'post_include_lines', 'libraries', 'library_dirs', + _ATTRIBUTES = ['pre_include_bits', 'includes', 'include_dirs', + 'post_include_bits', 'libraries', 'library_dirs', 'separate_module_sources', 'separate_module_files', 'export_symbols', 'compile_extra', 'link_extra', 'frameworks'] - _AVOID_DUPLICATES = ['separate_module_files', 'libraries', 'includes', - 'include_dirs', 'library_dirs', 'separate_module_sources'] + _DUPLICATES_OK = ['compile_extra', 'link_extra'] def __init__(self, - pre_include_lines = [], + pre_include_bits = [], includes = [], include_dirs = [], - post_include_lines = [], + post_include_bits = [], libraries = [], library_dirs = [], separate_module_sources = [], @@ -35,17 +34,18 @@ link_extra = [], frameworks = []): """ - pre_include_lines: list of lines that should be put at the top + pre_include_bits: list of pieces of text that should be put at the top of the generated .c files, before any #include. They shouldn't - contain an #include themselves. + contain an #include themselves. (Duplicate pieces are removed.) includes: list of .h file names to be #include'd from the generated .c files. include_dirs: list of dir names that is passed to the C compiler - post_include_lines: list of lines that should be put at the top - of the generated .c files, after the #includes. + post_include_bits: list of pieces of text that should be put at the top + of the generated .c files, after the #includes. (Duplicate pieces are + removed.) libraries: list of library names that is passed to the linker @@ -54,7 +54,7 @@ separate_module_sources: list of multiline strings that are each written to a .c file and compiled separately and linked later on. (If function prototypes are needed for other .c files - to access this, they can be put in post_include_lines.) + to access this, they can be put in post_include_bits.) separate_module_files: list of .c file names that are compiled separately and linked later on. (If an .h file is needed for @@ -83,7 +83,7 @@ """Returns a new ExternalCompilationInfo instance by parsing the string 'flags', which is in the typical Unix compiler flags format.""" - pre_include_lines = [] + pre_include_bits = [] include_dirs = [] compile_extra = [] for arg in flags.split(): @@ -95,13 +95,13 @@ macro, value = macro.split('=') else: value = '1' - pre_include_lines.append('#define %s %s' % (macro, value)) + pre_include_bits.append('#define %s %s' % (macro, value)) elif arg.startswith('-L') or arg.startswith('-l'): raise ValueError('linker flag found in compiler options: %r' % (arg,)) else: compile_extra.append(arg) - return cls(pre_include_lines=pre_include_lines, + return cls(pre_include_bits=pre_include_bits, include_dirs=include_dirs, compile_extra=compile_extra) from_compiler_flags = classmethod(from_compiler_flags) @@ -176,7 +176,7 @@ attrs = {} for name in self._ATTRIBUTES: - if name not in self._AVOID_DUPLICATES: + if name in self._DUPLICATES_OK: s = [] for i in [self] + others: s += getattr(i, name) @@ -193,12 +193,12 @@ return ExternalCompilationInfo(**attrs) def write_c_header(self, fileobj): - for line in self.pre_include_lines: - print >> fileobj, line + for piece in self.pre_include_bits: + print >> fileobj, piece for path in self.includes: print >> fileobj, '#include <%s>' % (path,) - for line in self.post_include_lines: - print >> fileobj, line + for piece in self.post_include_bits: + print >> fileobj, piece def _copy_attributes(self): d = {} Modified: pypy/dist/pypy/translator/tool/test/test_cbuild.py ============================================================================== --- pypy/dist/pypy/translator/tool/test/test_cbuild.py (original) +++ pypy/dist/pypy/translator/tool/test/test_cbuild.py Thu May 29 15:35:20 2008 @@ -58,38 +58,38 @@ def test_merge(self): e1 = ExternalCompilationInfo( - pre_include_lines = ['1'], + pre_include_bits = ['1'], includes = ['x.h'], - post_include_lines = ['p1'] + post_include_bits = ['p1'] ) e2 = ExternalCompilationInfo( - pre_include_lines = ['2'], + pre_include_bits = ['2'], includes = ['x.h', 'y.h'], - post_include_lines = ['p2'], + post_include_bits = ['p2'], ) e3 = ExternalCompilationInfo( - pre_include_lines = ['3'], + pre_include_bits = ['3'], includes = ['y.h', 'z.h'], - post_include_lines = ['p3'] + post_include_bits = ['p1', 'p3'] ) e = e1.merge(e2, e3) - assert e.pre_include_lines == ('1', '2', '3') + assert e.pre_include_bits == ('1', '2', '3') assert e.includes == ('x.h', 'y.h', 'z.h') - assert e.post_include_lines == ('p1', 'p2', 'p3') + assert e.post_include_bits == ('p1', 'p2', 'p3') def test_merge2(self): e1 = ExternalCompilationInfo( - pre_include_lines = ['1'], + pre_include_bits = ['1'], ) e2 = ExternalCompilationInfo( - pre_include_lines = ['2'], + pre_include_bits = ['2'], ) e3 = ExternalCompilationInfo( - pre_include_lines = ['3'], + pre_include_bits = ['3'], ) e = e1.merge(e2) e = e.merge(e3, e3) - assert e.pre_include_lines == ('1', '2', '3') + assert e.pre_include_bits == ('1', '2', '3') def test_convert_sources_to_c_files(self): eci = ExternalCompilationInfo( @@ -129,8 +129,8 @@ flags = ('-I/some/include/path -I/other/include/path ' '-DMACRO1 -D_MACRO2=baz -?1 -!2') eci = ExternalCompilationInfo.from_compiler_flags(flags) - assert eci.pre_include_lines == ('#define MACRO1 1', - '#define _MACRO2 baz') + assert eci.pre_include_bits == ('#define MACRO1 1', + '#define _MACRO2 baz') assert eci.includes == () assert eci.include_dirs == ('/some/include/path', '/other/include/path') From tverwaes at codespeak.net Thu May 29 16:10:43 2008 From: tverwaes at codespeak.net (tverwaes at codespeak.net) Date: Thu, 29 May 2008 16:10:43 +0200 (CEST) Subject: [pypy-svn] r55395 - pypy/dist/pypy/lang/smalltalk Message-ID: <20080529141043.3A3E3168548@codespeak.net> Author: tverwaes Date: Thu May 29 16:10:41 2008 New Revision: 55395 Modified: pypy/dist/pypy/lang/smalltalk/todo.txt Log: adding a todo Modified: pypy/dist/pypy/lang/smalltalk/todo.txt ============================================================================== --- pypy/dist/pypy/lang/smalltalk/todo.txt (original) +++ pypy/dist/pypy/lang/smalltalk/todo.txt Thu May 29 16:10:41 2008 @@ -18,3 +18,6 @@ Squeakimage: [ ] Implement image writer + +Shadows: +[ ] Fix invalidation of methoddictshadow when the w_self of its values array changes From arigo at codespeak.net Thu May 29 16:16:38 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 29 May 2008 16:16:38 +0200 (CEST) Subject: [pypy-svn] r55396 - in pypy/dist/pypy: rpython/module translator/c translator/tool Message-ID: <20080529141638.B095C168525@codespeak.net> Author: arigo Date: Thu May 29 16:16:37 2008 New Revision: 55396 Modified: pypy/dist/pypy/rpython/module/ll_os.py pypy/dist/pypy/translator/c/genc.py pypy/dist/pypy/translator/tool/cbuild.py Log: XXX horrible workaround for a bug of profiling in gcc on OS X with functions containing a direct call to fork() Modified: pypy/dist/pypy/rpython/module/ll_os.py ============================================================================== --- pypy/dist/pypy/rpython/module/ll_os.py (original) +++ pypy/dist/pypy/rpython/module/ll_os.py Thu May 29 16:16:37 2008 @@ -1121,7 +1121,18 @@ @registering_if(os, 'fork') def register_os_fork(self): - os_fork = self.llexternal('fork', [], rffi.PID_T) + # XXX horrible workaround for a bug of profiling in gcc on + # OS X with functions containing a direct call to fork() + eci = ExternalCompilationInfo( + post_include_bits = ['pid_t _noprof_fork(void);'], + separate_module_sources = [''' + /*--no-profiling-for-this-file!--*/ + pid_t _noprof_fork(void) { + return fork(); + } + ''']) + os_fork = self.llexternal('_noprof_fork', [], rffi.PID_T, + compilation_info = eci) def fork_llimpl(): childpid = rffi.cast(lltype.Signed, os_fork()) Modified: pypy/dist/pypy/translator/c/genc.py ============================================================================== --- pypy/dist/pypy/translator/c/genc.py (original) +++ pypy/dist/pypy/translator/c/genc.py Thu May 29 16:16:37 2008 @@ -399,9 +399,20 @@ cc = self.config.translation.cc else: cc = 'gcc' + make_no_prof = '' if self.has_profopt(): profopt = self.config.translation.profopt default_target = 'profopt' + # XXX horrible workaround for a bug of profiling in gcc on + # OS X with functions containing a direct call to fork() + non_profilable = [] + assert len(compiler.cfilenames) == len(ofiles) + for fn, oname in zip(compiler.cfilenames, ofiles): + fn = py.path.local(fn) + if '/*--no-profiling-for-this-file!--*/' in fn.read(): + non_profilable.append(oname) + if non_profilable: + make_no_prof = '$(MAKE) %s' % (' '.join(non_profilable),) else: profopt = '' default_target = '$(TARGET)' @@ -445,6 +456,7 @@ else: print >> f, 'TFLAGS = ' + '' print >> f, 'PROFOPT = ' + profopt + print >> f, 'MAKENOPROF = ' + make_no_prof print >> f, 'CC = ' + cc print >> f print >> f, MAKEFILE.strip() @@ -913,6 +925,7 @@ ABS_TARGET = $(shell python -c "import sys,os; print os.path.abspath(sys.argv[1])" $(TARGET)) profopt: +\t$(MAKENOPROF) # these files must be compiled without profiling \t$(MAKE) CFLAGS="-fprofile-generate $(CFLAGS)" LDFLAGS="-fprofile-generate $(LDFLAGS)" $(TARGET) \tcd $(PYPYDIR)/translator/goal && $(ABS_TARGET) $(PROFOPT) \t$(MAKE) clean_noprof Modified: pypy/dist/pypy/translator/tool/cbuild.py ============================================================================== --- pypy/dist/pypy/translator/tool/cbuild.py (original) +++ pypy/dist/pypy/translator/tool/cbuild.py Thu May 29 16:16:37 2008 @@ -578,10 +578,15 @@ for cfile in self.cfilenames: cfile = py.path.local(cfile) compile_extra = self.compile_extra[:] - # -frandom-seed is an attempted workaround for a bug with - # -fprofile-generate and -fprofile-use + # -frandom-seed is only to try to be as reproducable as possible if self.fix_gcc_random_seed: compile_extra.append('-frandom-seed=%s' % (cfile.basename,)) + # XXX horrible workaround for a bug of profiling in gcc on + # OS X with functions containing a direct call to fork() + if '/*--no-profiling-for-this-file!--*/' in cfile.read(): + compile_extra = [arg for arg in compile_extra + if not arg.startswith('-fprofile-')] + old = cfile.dirpath().chdir() try: res = compiler.compile([cfile.basename], From cami at codespeak.net Thu May 29 16:39:07 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Thu, 29 May 2008 16:39:07 +0200 (CEST) Subject: [pypy-svn] r55397 - in pypy/dist/pypy/lang/gameboy: . test Message-ID: <20080529143907.2B9B7168537@codespeak.net> Author: cami Date: Thu May 29 16:39:06 2008 New Revision: 55397 Modified: pypy/dist/pypy/lang/gameboy/cartridge.py pypy/dist/pypy/lang/gameboy/test/test_memory_bank_controller.py Log: added clock test for the memory bank controller fixed bug in the mbc3 clock_updat method which cause an endless loop Modified: pypy/dist/pypy/lang/gameboy/cartridge.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/cartridge.py (original) +++ pypy/dist/pypy/lang/gameboy/cartridge.py Thu May 29 16:39:06 2008 @@ -530,6 +530,7 @@ raise InvalidMemoryAccessException("MBC3.read_clock_data invalid address %i") def write(self, address, data): + print hex(address), hex(data) # 0000-1FFF if address <= 0x1FFF: self.write_ram_enable(address, data) @@ -585,7 +586,7 @@ self.clock_latched_seconds = self.clock_seconds self.clock_latched_minutes = self.clock_minutes self.clock_latched_hours = self.clock_hours - self.clock_latched_days = self.clock_days + self.clock_latched_days = self.clock_days & 0xFF self.clock_latched_control = (self.clock_control & 0xFE) | \ ((self.clock_days >> 8) & 0x01) @@ -598,39 +599,22 @@ elapsed += self.clock_minutes * 60 elapsed += self.clock_seconds - days = int(math.floor(elapsed / 24*60*60)) + days = int(math.floor(elapsed / (24.0*60*60.0))) self.clock_days += days elapsed -= days * 24*60*60 - #while elapsed >= 246060: - # elapsed -= 246060 - # self.clock_days+=1 - - hours = int(math.floor(elapsed / 60*60)) + + hours = int(math.floor(elapsed / (60*60))) self.clock_hours += hours elapsed -= hours * 60*60 - #while elapsed >= 6060: - # self.clock_hours+=1 - # elapsed -= 6060 minutes = int(math.floor(elapsed / 60)) self.clock_minutes += minutes - elapsed -= hours * 60 - #while elapsed >= 60: - # elapsed -= 60 - # self.clock_minutes+=1 + elapsed -= minutes * 60 self.clock_seconds += elapsed - #while self.clock_seconds >= 60: - # self.clock_seconds -= 60 - # self.clock_minutes+=1 - #while self.clock_minutes >= 60: - # self.clock_hours+=1 - # self.clock_minutes -= 60 - #while self.clock_hours >= 24: - # self.clock_hours -= 24 - # self.clock_days+=1 - while self.clock_days >= 512: - self.clock_days -= 512 + + if self.clock_days >= 512: + self.clock_days %= 512 self.clock_control |= 0x80 self.clock_time = now @@ -806,21 +790,19 @@ now = self.clock.get_time() elapsed = now - self.clock_time # years (4 bits) - while elapsed >= 365246060: - self.clock_register += 1 << 24 - elapsed -= 365246060 + years = int(math.floor(elapsed / (365*24*60*60))) + elapsed -= years*365*24*60*60 # days (12 bits) - while elapsed >= 246060: - self.clock_register += 1 << 12 - elapsed -= 246060 + days = int(math.floor(elapsed / (24*60*60))) + elapsed -= days*24*60*60 # minutes (12 bits) - while elapsed >= 60: - self.clock_register += 1 - elapsed -= 60 - if (self.clock_register & 0x0000FFF) >= 2460: - self.clock_register += (1 << 12) - 2460 - if (self.clock_register & 0x0FFF000) >= (365 << 12): - self.clock_register += (1 << 24) - (365 << 12) + minutes = int(math.floor(elapsed / 60)) + elapsed -= minutes*60 + + self.clock_register |= years << 24 + self.clock_register |= days << 12 + self.clock_register |= minutes + self.clock_time = now - elapsed Modified: pypy/dist/pypy/lang/gameboy/test/test_memory_bank_controller.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/test/test_memory_bank_controller.py (original) +++ pypy/dist/pypy/lang/gameboy/test/test_memory_bank_controller.py Thu May 29 16:39:06 2008 @@ -5,9 +5,18 @@ import py import pdb +class TestClock(object): + def __init__(self): + self.time = 0 + + def get_time(self): + return self.time + + def get_clock_driver(): return Clock() + RAM_SIZE = 3 ROM_SIZE = 2 @@ -286,12 +295,13 @@ value %= 0x0F # ----------------------------------------------------------------------------- - + def get_mbc3(rom_size=128, ram_size=4): - return MBC3(get_rom(rom_size), get_ram(ram_size), get_clock_driver()) + return MBC3(get_rom(rom_size), get_ram(ram_size), get_clock_driver()) + +get_mbc3() def test_mbc3_create(): - py.test.skip("takes too long") mbc = get_mbc3() fail_ini_test(mbc, 128, 0) fail_ini_test(mbc, 128, 5) @@ -300,11 +310,9 @@ basic_read_write_test(mbc, 0, 0x7FFF) def test_mbc3_write_ram_enable(): - py.test.skip("takes too long") write_ram_enable_test(get_mbc3()) def test_mbc3_write_rom_bank(): - py.test.skip("takes too long") mbc= get_mbc3() value = 1 for address in range(0x2000, 0x3FFF+1): @@ -319,7 +327,6 @@ value %= 0xFF def test_mbc3_write_ram_bank(): - py.test.skip("takes too long") mbc = get_mbc3() value = 1 for address in range(0x4000, 0x5FFF+1): @@ -334,7 +341,6 @@ value %= 0xFF def test_mbc3_write_clock_latch(): - py.test.skip("takes too long") mbc = get_mbc3() value = 1 for address in range(0x6000, 0x7FFF+1): @@ -348,20 +354,17 @@ value %= 0xFF def test_mbc3_read_write_ram(): - py.test.skip("takes too long") mbc = get_mbc3() value = 1 mbc.ram_enable = True for address in range(0xA000, 0xBFFF+1): mbc.write(address, value) - #pdb.runcall(mbc.write, address, value) assert mbc.ram[mbc.ram_bank + (address & 0x1FFF)] == value assert mbc.read(address) == value; value += 1 value %= 0xFF def test_mbc3_read_write_clock(): - py.test.skip("takes too long") mbc = get_mbc3() value = 1 mbc.ram_enable = True @@ -391,14 +394,70 @@ value += 1 value %= 0xFF - + def test_mbc3_update_clock(): - py.test.skip("not yet implemented") mbc = get_mbc3() + mbc.clock = TestClock() + mbc.clock.time = 1 + 2*60 + 3*60*60 + 4*24*60*60 + mbc.clock_days = 0 + mbc.clock_hours = 0 + mbc.clock_minutes = 0 + mbc.clock_seconds = 0 + mbc.clock_time = 0 + mbc.clock_control = 0xFF + mbc.update_clock() + assert mbc.clock_days == 0 + assert mbc.clock_hours == 0 + assert mbc.clock_minutes == 0 + assert mbc.clock_seconds == 0 + assert mbc.clock_time == mbc.clock.time + + mbc.clock_time = 0 + mbc.clock_control = 0x00 + mbc.update_clock() + assert mbc.clock_days == 4 + assert mbc.clock_hours == 3 + assert mbc.clock_minutes == 2 + assert mbc.clock_seconds == 1 + assert mbc.clock_time == mbc.clock.time + +def test_mbc3_update_clock_day_overflow(): + mbc = get_mbc3() + mbc.clock = TestClock() + mbc.clock.time = 2*512*24*60*60 + mbc.clock_days = 0 + mbc.clock_hours = 0 + mbc.clock_minutes = 0 + mbc.clock_seconds = 0 + mbc.clock_time = 0 + mbc.clock_control = 0x01 + mbc.update_clock() + assert mbc.clock_days == 0 + assert mbc.clock_hours == 0 + assert mbc.clock_minutes == 0 + assert mbc.clock_seconds == 0 + assert mbc.clock_control == 0x81 def test_mbc3_latch_clock(): - py.test.skip("not yet implemented") mbc = get_mbc3() + mbc.clock = TestClock() + mbc.clock.time = 1 + 2*60 + 3*60*60 + (0xFF+2)*24*60*60 + mbc.clock_days = 0 + mbc.clock_hours = 0 + mbc.clock_minutes = 0 + mbc.clock_seconds = 0 + mbc.clock_time = 0 + mbc.clock_control = 0x00 + mbc.latch_clock() + assert mbc.clock_days == 0xFF+2 + assert mbc.clock_latched_days == (0xFF+2) & 0xFF + assert mbc.clock_hours == 3 + assert mbc.clock_latched_hours == 3 + assert mbc.clock_minutes == 2 + assert mbc.clock_latched_minutes == 2 + assert mbc.clock_seconds == 1 + assert mbc.clock_latched_seconds == 1 + assert mbc.clock_latched_control == (mbc.clock_days>>8) & 0x01 # ----------------------------------------------------------------------------- @@ -559,7 +618,6 @@ value %= 0xFF def test_huc3_write_clock_register_clock_shift(): - #py.test.skip("bug for in the clock") mbc = get_huc3() value = 1 mbc.ram_flag = 0x0B @@ -593,10 +651,17 @@ value = +1 value %= 0xF + def test_huc3_update_clock(): - py.test.skip("not yet implemented") mbc = get_huc3() - pass - + mbc.clock = TestClock() + mbc.clock.time = 1*60 + 2*24*60*60 + 3*365*24*60*60 + mbc.clock_register = 0x00 + mbc.clock_time = 0 + mbc.update_clock() + assert mbc.clock_register & 0x00000FFF == 1 + assert mbc.clock_register & 0x00FFF000 == 2 << 12 + assert mbc.clock_register & 0xFF000000 == 3 << 24 + assert mbc.clock_time == mbc.clock.time # ----------------------------------------------------------------------------- From cami at codespeak.net Thu May 29 16:59:02 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Thu, 29 May 2008 16:59:02 +0200 (CEST) Subject: [pypy-svn] r55398 - in pypy/dist/pypy/lang/gameboy: . test Message-ID: <20080529145902.360FE168529@codespeak.net> Author: cami Date: Thu May 29 16:59:00 2008 New Revision: 55398 Modified: pypy/dist/pypy/lang/gameboy/cartridge.py pypy/dist/pypy/lang/gameboy/gameboy.py pypy/dist/pypy/lang/gameboy/gameboyImplementation.py pypy/dist/pypy/lang/gameboy/interrupt.py pypy/dist/pypy/lang/gameboy/joypad.py pypy/dist/pypy/lang/gameboy/ram.py pypy/dist/pypy/lang/gameboy/serial.py pypy/dist/pypy/lang/gameboy/test/test_ram.py pypy/dist/pypy/lang/gameboy/test/test_serial.py pypy/dist/pypy/lang/gameboy/video.py Log: minor code refactoring, mostly updating comments adapted tests to the refactoring activated nintendo startup Modified: pypy/dist/pypy/lang/gameboy/cartridge.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/cartridge.py (original) +++ pypy/dist/pypy/lang/gameboy/cartridge.py Thu May 29 16:59:00 2008 @@ -69,9 +69,9 @@ def __init__(self, clock): assert isinstance(clock, Clock) - self.clock = clock + self.clock = clock self.cartridge = None - self.mbc = None + self.mbc = None def reset(self): if not self.has_battery(): @@ -592,31 +592,32 @@ def update_clock(self): now = self.clock.get_time() - if (self.clock_control & 0x40) == 0: - elapsed = now - self.clock_time - elapsed += self.clock_days * 24*60*60 - elapsed += self.clock_hours * 60*60 - elapsed += self.clock_minutes * 60 - elapsed += self.clock_seconds - - days = int(math.floor(elapsed / (24.0*60*60.0))) - self.clock_days += days - elapsed -= days * 24*60*60 - - hours = int(math.floor(elapsed / (60*60))) - self.clock_hours += hours - elapsed -= hours * 60*60 - - minutes = int(math.floor(elapsed / 60)) - self.clock_minutes += minutes - elapsed -= minutes * 60 - - self.clock_seconds += elapsed - - if self.clock_days >= 512: - self.clock_days %= 512 - self.clock_control |= 0x80 + elapsed = now - self.clock_time self.clock_time = now + if (self.clock_control & 0x40) != 0: + return + elapsed += self.clock_days * 24*60*60 + elapsed += self.clock_hours * 60*60 + elapsed += self.clock_minutes * 60 + elapsed += self.clock_seconds + + days = int(math.floor(elapsed / (24.0*60*60.0))) + self.clock_days += days + elapsed -= days * 24*60*60 + + hours = int(math.floor(elapsed / (60*60))) + self.clock_hours += hours + elapsed -= hours * 60*60 + + minutes = int(math.floor(elapsed / 60)) + self.clock_minutes += minutes + elapsed -= minutes * 60 + + self.clock_seconds += elapsed + + if self.clock_days >= 512: + self.clock_days %= 512 + self.clock_control |= 0x80 #------------------------------------------------------------------------------- Modified: pypy/dist/pypy/lang/gameboy/gameboy.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/gameboy.py (original) +++ pypy/dist/pypy/lang/gameboy/gameboy.py Thu May 29 16:59:00 2008 @@ -47,6 +47,7 @@ def load_cartridge(self, cartridge, verify=True): self.cartridge_manager.load(cartridge, verify) self.cpu.set_rom(self.cartridge_manager.get_rom()) + self.memory_bank_controller = self.cartridge_manager.get_memory_bank() def load_cartridge_file(self, path, verify=True): self.load_cartridge(CartridgeFile(path), verify) @@ -58,7 +59,7 @@ self.video.set_frame_skip(frameSkip) def save(self, cartridgeName): - self.cartridge.save(cartridgeName) + self.cartridge_manager.save(cartridgeName) def start(self): self.sound.start() @@ -68,7 +69,7 @@ def reset(self): self.ram.reset() - self.cartridge.reset() + self.memory_bank_controller.reset() self.interrupt.reset() self.cpu.reset() self.serial.reset() @@ -180,23 +181,23 @@ def draw_logo(self): for index in range(0, 48): - bits = self.cartridge.read(0x0104 + index) - pattern0 = ((bits >> 0) & 0x80) + ((bits >> 1) & 0x60)\ - + ((bits >> 2) & 0x18) + ((bits >> 3) & 0x06)\ - + ((bits >> 4) & 0x01) - - pattern1 = ((bits << 4) & 0x80) + ((bits << 3) & 0x60)\ - + ((bits << 2) & 0x18) + ((bits << 1) & 0x06)\ - + ((bits << 0) & 0x01) + bits = self.memory_bank_controller.read(0x0104 + index) + pattern0 = ((bits >> 0) & 0x80) + ((bits >> 1) & 0x60) + \ + ((bits >> 2) & 0x18) + ((bits >> 3) & 0x06) + \ + ((bits >> 4) & 0x01) + + pattern1 = ((bits << 4) & 0x80) + ((bits << 3) & 0x60) + \ + ((bits << 2) & 0x18) + ((bits << 1) & 0x06) + \ + ((bits << 0) & 0x01) self.video.write(0x8010 + (index << 3), pattern0) self.video.write(0x8012 + (index << 3), pattern0) - self.video.write(0x8014 + (index << 3), pattern1) self.video.write(0x8016 + (index << 3), pattern1) for index in range(0, 8): - self.video.write(0x8190 + (index << 1), constants.REGISTERED_BITMAP[index]) + self.video.write(0x8190 + (index << 1), \ + constants.REGISTERED_BITMAP[index]) for tile in range(0, 12): self.video.write(0x9904 + tile, tile + 1) Modified: pypy/dist/pypy/lang/gameboy/gameboyImplementation.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/gameboyImplementation.py (original) +++ pypy/dist/pypy/lang/gameboy/gameboyImplementation.py Thu May 29 16:59:00 2008 @@ -32,6 +32,7 @@ def mainLoop(self): + self.reset() try: while True: if self.poll_event(): Modified: pypy/dist/pypy/lang/gameboy/interrupt.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/interrupt.py (original) +++ pypy/dist/pypy/lang/gameboy/interrupt.py Thu May 29 16:59:00 2008 @@ -5,8 +5,8 @@ class InterruptFlag(object): def __init__(self, _reset, mask, call_code): - self._reset = _reset - self.mask = mask + self._reset = _reset + self.mask = mask self.call_code = call_code self.reset() @@ -34,18 +34,15 @@ self.reset() def create_interrupt_flags(self): - self.vblank = InterruptFlag(True, constants.VBLANK, 0x40) + self.vblank = InterruptFlag(True, constants.VBLANK, 0x40) self.lcd = InterruptFlag(False, constants.LCD, 0x48) self.timer = InterruptFlag(False, constants.TIMER, 0x50) self.serial = InterruptFlag(False, constants.SERIAL, 0x58) self.joypad = InterruptFlag(False, constants.JOYPAD, 0x60) def create_flag_list(self): - self.interrupt_flags = [ - self.vblank, self.lcd, - self.timer, self.serial, - self.joypad - ] + self.interrupt_flags = [ self.vblank, self.lcd, self.timer, self.serial, + self.joypad] def create_flag_mask_mapping(self): self.mask_mapping = {} Modified: pypy/dist/pypy/lang/gameboy/joypad.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/joypad.py (original) +++ pypy/dist/pypy/lang/gameboy/joypad.py Thu May 29 16:59:00 2008 @@ -26,7 +26,6 @@ return self.cycles def emulate(self, ticks): - ticks = int(ticks) self.cycles -= ticks if self.cycles <= 0: if self.driver.is_raised(): @@ -34,13 +33,11 @@ self.cycles = constants.JOYPAD_CLOCK def write(self, address, data): - address = int(address) if address == constants.JOYP: self.joyp = (self.joyp & 0xC) + (data & 0x3) self.update() def read(self, address): - address = int(address) if address == constants.JOYP: return (self.joyp << 4) + self.button_code return 0xFF Modified: pypy/dist/pypy/lang/gameboy/ram.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/ram.py (original) +++ pypy/dist/pypy/lang/gameboy/ram.py Thu May 29 16:59:00 2008 @@ -18,35 +18,32 @@ def __init__(self): # Work RAM - self.w_ram = [0]*8192 + self.work_ram = [0]*8192 # High RAM - self.h_ram = [0]*128 + self.hi_ram = [0]*128 self.reset() def reset(self): # Work RAM - self.w_ram = [0]*8192 + self.work_ram = [0]*8192 # High RAM - self.h_ram = [0]*128 + self.hi_ram = [0]*128 def write(self, address, data): - address = int(address) - data = int(data) # C000-DFFF Work RAM (8KB) # E000-FDFF Echo RAM if address >= 0xC000 and address <= 0xFDFF: - self.w_ram[address & 0x1FFF] = data + self.work_ram[address & 0x1FFF] = data # FF80-FFFE High RAM elif address >= 0xFF80 and address <= 0xFFFE: - self.h_ram[address & 0x7F] = data + self.hi_ram[address & 0x7F] = data def read(self, address): - address = int(address) # C000-DFFF Work RAM # E000-FDFF Echo RAM if address >= 0xC000 and address <= 0xFDFF: - return self.w_ram[address & 0x1FFF] & 0xFF + return self.work_ram[address & 0x1FFF] & 0xFF # FF80-FFFE High RAM elif address >= 0xFF80 and address <= 0xFFFE: - return self.h_ram[address & 0x7F] & 0xFF + return self.hi_ram[address & 0x7F] & 0xFF raise Exception("Invalid Memory access, address out of range") \ No newline at end of file Modified: pypy/dist/pypy/lang/gameboy/serial.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/serial.py (original) +++ pypy/dist/pypy/lang/gameboy/serial.py Thu May 29 16:59:00 2008 @@ -16,36 +16,35 @@ def reset(self): self.cycles = int(constants.SERIAL_CLOCK) - self.sb = 0x00 - self.sc = 0x00 + self.serial_data = 0x00 + self.serial_control = 0x00 def get_cycles(self): return self.cycles def emulate(self, ticks): - ticks = int(ticks) - if (self.sc & 0x81) != 0x81: + if (self.serial_control & 0x81) != 0x81: return self.cycles -= ticks if self.cycles <= 0: - self.sb = 0xFF - self.sc &= 0x7F + self.serial_data = 0xFF + self.serial_control &= 0x7F self.cycles = constants.SERIAL_IDLE_CLOCK self.interrupt.raise_interrupt(constants.SERIAL) def set_serial_data(self, data): - self.sb = data + self.serial_data = data def set_serial_control(self, data): - self.sc = data - # HACK: delay the serial interrupt (Shin Nihon Pro Wrestling) + self.serial_control = data + # HACK: delay the serial interrupt self.cycles = constants.SERIAL_IDLE_CLOCK + constants.SERIAL_CLOCK def get_serial_data(self): - return self.sb + return self.serial_data def get_serial_control(self): - return self.sc + return self.serial_control def write(self, address, data): address = int(address) Modified: pypy/dist/pypy/lang/gameboy/test/test_ram.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/test/test_ram.py (original) +++ pypy/dist/pypy/lang/gameboy/test/test_ram.py Thu May 29 16:59:00 2008 @@ -17,36 +17,36 @@ except Exception: pass - assert value not in ram.w_ram - assert value not in ram.h_ram + assert value not in ram.work_ram + assert value not in ram.hi_ram address = 0xC000 ram.write(address, value) assert ram.read(address) == value - assert value in ram.w_ram - assert value not in ram.h_ram + assert value in ram.work_ram + assert value not in ram.hi_ram address = 0xFDFF value += 1 ram.write(address, value) assert ram.read(address) == value - assert value in ram.w_ram - assert value not in ram.h_ram + assert value in ram.work_ram + assert value not in ram.hi_ram address = 0xFF80 value += 1 ram.write(address, value) assert ram.read(address) == value - assert value in ram.h_ram - assert value not in ram.w_ram + assert value in ram.hi_ram + assert value not in ram.work_ram address = 0xFFFE value += 1 ram.write(address, value) assert ram.read(address) == value - assert value in ram.h_ram - assert value not in ram.w_ram + assert value in ram.hi_ram + assert value not in ram.work_ram address += 1 value += 1 @@ -56,5 +56,5 @@ py.test.fail() except Exception: pass - assert value not in ram.h_ram - assert value not in ram.w_ram \ No newline at end of file + assert value not in ram.hi_ram + assert value not in ram.work_ram \ No newline at end of file Modified: pypy/dist/pypy/lang/gameboy/test/test_serial.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/test/test_serial.py (original) +++ pypy/dist/pypy/lang/gameboy/test/test_serial.py Thu May 29 16:59:00 2008 @@ -9,13 +9,13 @@ def test_reset(): serial = get_serial() - serial.cycles = 12 - serial.sb = 12 - serial.sc = 12 + serial.cycles = 12 + serial.serial_data = 12 + serial.serial_control = 12 serial.reset() - assert serial.cycles == constants.SERIAL_CLOCK - assert serial.sb == 0 - assert serial.sc == 0 + assert serial.cycles == constants.SERIAL_CLOCK + assert serial.serial_data == 0 + assert serial.serial_control == 0 def test_set_serial_control(): @@ -28,30 +28,30 @@ def test_emulate(): serial = get_serial() - serial.sc = 0x00 + serial.serial_control = 0x00 serial.emulate(20) - assert serial.cycles == constants.SERIAL_CLOCK - assert serial.sb == 0 - assert serial.sc == 0 + assert serial.cycles == constants.SERIAL_CLOCK + assert serial.serial_data == 0 + assert serial.serial_control == 0 serial.reset() - serial.sc = 0x81 + serial.serial_control = 0x81 serial.cycles = 10 cycles = serial.cycles serial.emulate(2) assert serial.cycles > 0 - assert cycles-serial.cycles == 2 - assert serial.sb == 0 - assert serial.sc == 0x81 + assert cycles-serial.cycles == 2 + assert serial.serial_data == 0 + assert serial.serial_control == 0x81 assert serial.interrupt.serial.is_pending() == False serial.reset() - serial.sc = 0x81 + serial.serial_control = 0x81 serial.cycles = 0 serial.emulate(2) - assert serial.sb == 0xFF - assert serial.sc == 0x81 & 0x7F - assert serial.cycles == constants.SERIAL_IDLE_CLOCK + assert serial.serial_data == 0xFF + assert serial.serial_control == 0x81 & 0x7F + assert serial.cycles == constants.SERIAL_IDLE_CLOCK assert serial.interrupt.serial.is_pending() == True @@ -60,12 +60,12 @@ value = 0x12 serial.write(constants.SB, value) assert serial.read(constants.SB) == value - assert serial.sb == value + assert serial.serial_data == value value += 1 serial.write(constants.SC, value) assert serial.read(constants.SC) == value - assert serial.sc == value + assert serial.serial_control == value assert serial.read(0) == 0xFF \ No newline at end of file Modified: pypy/dist/pypy/lang/gameboy/video.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/video.py (original) +++ pypy/dist/pypy/lang/gameboy/video.py Thu May 29 16:59:00 2008 @@ -43,7 +43,7 @@ self.h_blank_interrupt = False self.oam_interrupt = False self.h_blank_interrupt = False - self.vblank_interrupt = False + self.vblank_interrupt = False #Coincidence Flag (0:LYC<>LY, 1:LYC=LY) self.coincidence_flag = False @@ -68,7 +68,7 @@ #frames = 0 #frame_skip = 0 - # Line Buffer, constants.OAM Cache and Color Palette + # Line Buffer, OAM Cache and Color Palette #line = []#= new int[8 + 160 + 8] #objects = []#= new int[OBJECTS_PER_LINE] #palette = []#= new int[1024] @@ -88,7 +88,7 @@ def reset(self): self.cycles = constants.MODE_2_TICKS - # used for enabled or disablind window or background + # used for enabled or disabled window or background # Bit 7 - LCD Display Enable (0=Off, 1=On) # Bit 6 - Window Tile Map Display Select (0=9800-9BFF, 1=9C00-9FFF) # Bit 5 - Window Display Enable (0=Off, 1=On) @@ -367,7 +367,7 @@ def emulate_hblank_line_y_compare(self): if self.line_y == self.line_y_compare: - # constants.LYC=LY interrupt + # LYC=LY interrupt self.stat |= 0x04 if (self.stat & 0x40) != 0: self.interrupt.raise_interrupt(constants.LCD) @@ -377,7 +377,7 @@ def emulate_hblank_part_1(self): self.stat = (self.stat & 0xFC) | 0x02 self.cycles += constants.MODE_2_TICKS - # constants.OAM interrupt + # OAM interrupt if (self.stat & 0x20) != 0 and (self.stat & 0x44) != 0x44: self.interrupt.raise_interrupt(constants.LCD) @@ -390,7 +390,6 @@ self.frames = 0 else: self.display = False - self.stat = (self.stat & 0xFC) | 0x01 self.cycles += constants.MODE_1_BEGIN_TICKS self.vblank = True @@ -416,7 +415,7 @@ def emulate_vblank_first_y_line(self): self.stat = (self.stat & 0xFC) | 0x02 self.cycles += constants.MODE_2_TICKS - # constants.OAM interrupt + #OAM interrupt if (self.stat & 0x20) != 0 and (self.stat & 0x44) != 0x44: self.interrupt.raise_interrupt(constants.LCD) @@ -433,7 +432,7 @@ self.stat = (self.stat & 0xFC) | 0x01 self.cycles += constants.MODE_1_TICKS - constants.MODE_1_END_TICKS if self.line_y == self.line_y_compare: - # constants.LYC=LY interrupt + #LYC=LY interrupt self.stat |= 0x04 if (self.stat & 0x40) != 0: self.interrupt.raise_interrupt(constants.LCD) @@ -642,10 +641,10 @@ #color if (pattern & 0x22) == 0 or ((pattern & 0x08) != 0 and \ (pattern & 0x11) != 0): - # constants.OBJ behind constants.BG color 1-3 + # OBJ behind BG color 1-3 color = (self.background_palette >> ((((pattern >> 3) & 0x02) +\ (pattern & 0x01)) << 1)) & 0x03 - # constants.OBJ above constants.BG + # OBJ above BG elif ((pattern & 0x04) == 0): color = (self.object_palette_0 >> ((((pattern >> 4) & 0x02) + \ ((pattern >> 1) & 0x01)) << 1)) & 0x03 From fijal at codespeak.net Thu May 29 17:42:03 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 29 May 2008 17:42:03 +0200 (CEST) Subject: [pypy-svn] r55399 - pypy/django/tests/regressiontests/dispatch/tests Message-ID: <20080529154203.E075C168516@codespeak.net> Author: fijal Date: Thu May 29 17:42:00 2008 New Revision: 55399 Modified: pypy/django/tests/regressiontests/dispatch/tests/test_dispatcher.py Log: Put few gc.collect here and there, doesn't make issue go away though Modified: pypy/django/tests/regressiontests/dispatch/tests/test_dispatcher.py ============================================================================== --- pypy/django/tests/regressiontests/dispatch/tests/test_dispatcher.py (original) +++ pypy/django/tests/regressiontests/dispatch/tests/test_dispatcher.py Thu May 29 17:42:00 2008 @@ -2,6 +2,7 @@ from django.dispatch import dispatcher, robust import unittest import copy +import gc def x(a): return a @@ -89,6 +90,7 @@ result = send('this',b, a=b) self.assertEqual(result, expected) self.assertEqual(list(getAllReceivers(b,signal)), []) + gc.collect() self._testIsClean() def testGarbageCollectedObj(self): @@ -104,6 +106,7 @@ result = send('this',b, a=b) self.assertEqual(result, expected) self.assertEqual(list(getAllReceivers(b,signal)), []) + gc.collect() self._testIsClean() @@ -123,6 +126,7 @@ del a del b del result + gc.collect() self._testIsClean() def testRobust(self): From fijal at codespeak.net Thu May 29 18:56:37 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 29 May 2008 18:56:37 +0200 (CEST) Subject: [pypy-svn] r55401 - pypy/dist/pypy/module/__builtin__ Message-ID: <20080529165637.450B41684FC@codespeak.net> Author: fijal Date: Thu May 29 18:56:34 2008 New Revision: 55401 Modified: pypy/dist/pypy/module/__builtin__/app_misc.py pypy/dist/pypy/module/__builtin__/importing.py Log: Save sys_importer_cache from variable leaking from last iteration. Still thinking about test... Modified: pypy/dist/pypy/module/__builtin__/app_misc.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/app_misc.py (original) +++ pypy/dist/pypy/module/__builtin__/app_misc.py Thu May 29 18:56:34 2008 @@ -24,6 +24,7 @@ importer = importer_cache.get(p) else: importer_cache[p] = None + importer = None for hook in path_hooks: try: importer = hook(p) Modified: pypy/dist/pypy/module/__builtin__/importing.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/importing.py (original) +++ pypy/dist/pypy/module/__builtin__/importing.py Thu May 29 18:56:34 2008 @@ -590,6 +590,7 @@ importer = importer_cache.get(p) else: importer_cache[p] = None + importer = None for hook in path_hooks: try: importer = hook(p) From afa at codespeak.net Thu May 29 18:58:19 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Thu, 29 May 2008 18:58:19 +0200 (CEST) Subject: [pypy-svn] r55402 - pypy/branch/build-external/pypy/rlib Message-ID: <20080529165819.E615B1684FB@codespeak.net> Author: afa Date: Thu May 29 18:58:17 2008 New Revision: 55402 Modified: pypy/branch/build-external/pypy/rlib/rzipfile.py pypy/branch/build-external/pypy/rlib/rzlib.py Log: These eci will be used alone (not merged to others) Modified: pypy/branch/build-external/pypy/rlib/rzipfile.py ============================================================================== --- pypy/branch/build-external/pypy/rlib/rzipfile.py (original) +++ pypy/branch/build-external/pypy/rlib/rzipfile.py Thu May 29 18:58:17 2008 @@ -142,6 +142,7 @@ def __init__(self, zipname, mode='r', compression=ZIP_STORED): if mode != 'r': raise TypeError("Read only support by now") + mode = mode + 'b' self.compression = compression self.filename = zipname self.mode = mode Modified: pypy/branch/build-external/pypy/rlib/rzlib.py ============================================================================== --- pypy/branch/build-external/pypy/rlib/rzlib.py (original) +++ pypy/branch/build-external/pypy/rlib/rzlib.py Thu May 29 18:58:17 2008 @@ -46,7 +46,8 @@ Definitions for basic types defined by zlib. """ _compilation_info_ = ExternalCompilationInfo( - includes = includes + includes = includes, + include_dirs = [zlib_home], ) # XXX If Z_PREFIX was defined for the libz build, then these types are @@ -90,7 +91,8 @@ definitions. """ _compilation_info_ = ExternalCompilationInfo( - includes = includes + includes = includes, + include_dirs = [zlib_home], ) z_stream = rffi_platform.Struct( From fijal at codespeak.net Thu May 29 18:58:45 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 29 May 2008 18:58:45 +0200 (CEST) Subject: [pypy-svn] r55403 - pypy/dist/pypy/module/zipimport Message-ID: <20080529165845.23335168500@codespeak.net> Author: fijal Date: Thu May 29 18:58:44 2008 New Revision: 55403 Modified: pypy/dist/pypy/module/zipimport/interp_zipimport.py Log: Cosmetic fix for cpython regr test suite (__loader__ needs to be available before module body runs) Modified: pypy/dist/pypy/module/zipimport/interp_zipimport.py ============================================================================== --- pypy/dist/pypy/module/zipimport/interp_zipimport.py (original) +++ pypy/dist/pypy/module/zipimport/interp_zipimport.py Thu May 29 18:58:44 2008 @@ -144,10 +144,10 @@ w = space.wrap w_mod = w(Module(space, w(modname))) real_name = self.name + os.path.sep + filename + space.setattr(w_mod, w('__loader__'), space.wrap(self)) importing._prepare_module(space, w_mod, real_name, pkgpath) result = importing.load_source_module(space, w(modname), w_mod, filename, buf, write_pyc=False) - space.setattr(w_mod, w('__loader__'), space.wrap(self)) return result def _parse_mtime(self, space, filename): @@ -192,11 +192,11 @@ 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 + 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, filename, magic, timestamp, buf) - space.setattr(w_mod, w('__loader__'), space.wrap(self)) return result def have_modulefile(self, space, filename): From afa at codespeak.net Thu May 29 19:04:21 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Thu, 29 May 2008 19:04:21 +0200 (CEST) Subject: [pypy-svn] r55404 - in pypy/branch/build-external/pypy: rpython/tool translator/c translator/tool translator/tool/test Message-ID: <20080529170421.421BE168477@codespeak.net> Author: afa Date: Thu May 29 19:04:20 2008 New Revision: 55404 Modified: pypy/branch/build-external/pypy/rpython/tool/rffi_platform.py pypy/branch/build-external/pypy/translator/c/genc.py pypy/branch/build-external/pypy/translator/tool/cbuild.py pypy/branch/build-external/pypy/translator/tool/test/test_cbuild.py Log: Compile separate_modules_files separately, using only the CompilationInfo they belong to. Modified: pypy/branch/build-external/pypy/rpython/tool/rffi_platform.py ============================================================================== --- pypy/branch/build-external/pypy/rpython/tool/rffi_platform.py (original) +++ pypy/branch/build-external/pypy/rpython/tool/rffi_platform.py Thu May 29 19:04:20 2008 @@ -537,9 +537,8 @@ """ def run_example_code(filepath, eci): - eci = eci.convert_sources_to_files(being_main=True) - files = [filepath] + [py.path.local(f) for f in eci.separate_module_files] - output = build_executable_cache(files, eci) + eci = eci.compile_separate_files(being_main=True) + output = build_executable_cache([filepath], eci) section = None for line in output.splitlines(): line = line.strip() Modified: pypy/branch/build-external/pypy/translator/c/genc.py ============================================================================== --- pypy/branch/build-external/pypy/translator/c/genc.py (original) +++ pypy/branch/build-external/pypy/translator/c/genc.py Thu May 29 19:04:20 2008 @@ -7,7 +7,7 @@ from pypy.translator.llsupport.wrapper import new_wrapper from pypy.translator.gensupp import uniquemodulename, NameManager from pypy.translator.tool.cbuild import so_ext, ExternalCompilationInfo -from pypy.translator.tool.cbuild import compile_c_module +from pypy.translator.tool.cbuild import compile_c_module, external_dir from pypy.translator.tool.cbuild import CCompiler, ProfOpt from pypy.translator.tool.cbuild import import_module_from_directory from pypy.translator.tool.cbuild import check_under_under_thread @@ -125,6 +125,9 @@ defines['RPY_SANDBOXED'] = 1 if CBuilder.have___thread is None: CBuilder.have___thread = check_under_under_thread() + + self.eci = self.eci.compile_separate_files(being_main=self.standalone) + if not self.standalone: assert not self.config.translation.instrument cfile, extra = gen_source(db, modulename, targetdir, self.eci, @@ -308,7 +311,14 @@ extrafiles = [] for fn in self.extrafiles: fn = py.path.local(fn) - if not fn.relto(udir): + if fn.relto(udir): + pass + elif fn.relto(external_dir): + newname = self.targetdir.join(fn.relto(external_dir)) + newname.ensure() + fn.copy(newname) + fn = newname + else: newname = self.targetdir.join(fn.basename) fn.copy(newname) fn = newname @@ -374,7 +384,7 @@ if fn.dirpath() == targetdir: name = fn.basename else: - assert fn.dirpath().dirpath() == udir + assert fn.relto(udir) name = '../' + fn.relto(udir) name = name.replace("\\", "/") @@ -762,8 +772,7 @@ print >>fi, "#define INSTRUMENT_NCOUNTER %d" % n fi.close() - eci = eci.convert_sources_to_files(being_main=True) - return filename, sg.getextrafiles() + list(eci.separate_module_files) + return filename, sg.getextrafiles() def gen_source(database, modulename, targetdir, eci, defines={}): @@ -822,9 +831,8 @@ libraries = eci.libraries f.write(SETUP_PY % locals()) f.close() - eci = eci.convert_sources_to_files(being_main=True) - return filename, sg.getextrafiles() + list(eci.separate_module_files) + return filename, sg.getextrafiles() SETUP_PY = ''' Modified: pypy/branch/build-external/pypy/translator/tool/cbuild.py ============================================================================== --- pypy/branch/build-external/pypy/translator/tool/cbuild.py (original) +++ pypy/branch/build-external/pypy/translator/tool/cbuild.py Thu May 29 19:04:20 2008 @@ -19,7 +19,8 @@ _ATTRIBUTES = ['pre_include_lines', 'includes', 'include_dirs', 'post_include_lines', 'libraries', 'library_dirs', 'separate_module_sources', 'separate_module_files', - 'export_symbols', 'compile_extra', 'link_extra', 'frameworks'] + 'export_symbols', 'compile_extra', 'link_extra', + 'extra_objects', 'frameworks'] _AVOID_DUPLICATES = ['separate_module_files', 'libraries', 'includes', 'include_dirs', 'library_dirs', 'separate_module_sources'] @@ -35,6 +36,7 @@ export_symbols = [], compile_extra = [], link_extra = [], + extra_objects = [], frameworks = []): """ pre_include_lines: list of lines that should be put at the top @@ -71,6 +73,8 @@ link_extra: list of parameters which will be directly passed to the linker + extra_objects: list of object files to add to the linker + frameworks: list of Mac OS X frameworks which should passed to the linker. Use this instead of the 'libraries' parameter if you want to link to a framework bundle. Not suitable for unix-like .dylib @@ -208,14 +212,53 @@ d[attr] = getattr(self, attr) return d + def compile_shared_lib(self, being_main=False): + eci = self.compile_separate_files(being_main=being_main) + if eci is self: + return self + lib = compile_c_module([], 'externmod', eci) + d = eci._copy_attributes() + d['libraries'] += (lib,) + d['separate_module_files'] = () + d['separate_module_sources'] = () + d['extra_objects'] = [] + return ExternalCompilationInfo(**d) + + def compile_separate_files(self, being_main=False): + cs = CompilationSet(self, + self.separate_module_files, + self.separate_module_sources) + cs = cs.convert_sources_to_files(being_main=being_main) + objects = cs.compile_objects() + if not objects: + return self + d = self._copy_attributes() + d['extra_objects'] += tuple(objects) + d['separate_module_files'] = () + d['separate_module_sources'] = () + return ExternalCompilationInfo(**d) + + +class CompilationSet: + "A set of source files sharing the same compilation options" + def __init__(self, eci, files=None, sources=None): + self.objects = [] + self.eci = eci + if files is None: + files = [] + self.files = files + if sources is None: + sources = [] + self.sources = sources + def convert_sources_to_files(self, cache_dir=None, being_main=False): - if not self.separate_module_sources: + if not self.sources: return self if cache_dir is None: cache_dir = udir.join('module_cache').ensure(dir=1) num = 0 files = [] - for source in self.separate_module_sources: + for source in self.sources: while 1: filename = cache_dir.join('module_%d.c' % num) num += 1 @@ -224,29 +267,40 @@ f = filename.open("w") if being_main: f.write("#define PYPY_NOT_MAIN_FILE\n") - self.write_c_header(f) + self.eci.write_c_header(f) source = str(source) f.write(source) if not source.endswith('\n'): f.write('\n') f.close() files.append(str(filename)) - d = self._copy_attributes() - d['separate_module_sources'] = () - d['separate_module_files'] += tuple(files) - return ExternalCompilationInfo(**d) + return CompilationSet(self.eci, + files=list(self.files) + files, + sources=None) + + def compile_objects(self): + cs = self.convert_sources_to_files() + if not cs.files: + return [] + from distutils.ccompiler import new_compiler - def compile_shared_lib(self): - self = self.convert_sources_to_files() - if not self.separate_module_files: - return self - lib = compile_c_module([], 'externmod', self) - d = self._copy_attributes() - d['libraries'] += (lib,) - d['separate_module_files'] = () - d['separate_module_sources'] = () - return ExternalCompilationInfo(**d) + compiler = new_compiler(force=1) + + files = [py.path.local(f).relto(udir) for f in cs.files] + files = [str(f) for f in cs.files] + old = udir.chdir() + try: + objects = compiler.compile( + files, + include_dirs=self.eci.include_dirs, + ) + objects = [str(py.path.local(o)) for o in objects] + finally: + old.chdir() + + return objects + if sys.platform == 'win32': so_ext = '.dll' else: @@ -281,6 +335,74 @@ opt += '/Op' gcv['OPT'] = opt +def compile_shared_library(modname, cfiles, extension_options): + from distutils.dist import Distribution + from distutils.extension import Extension + from distutils.ccompiler import get_default_compiler + from distutils.command.build_ext import build_ext + + class build_shared_library(build_ext): + """ We build shared libraries, not python modules. + On windows, avoid to export the initXXX function, + and don't use a .pyd extension. """ + def get_export_symbols(self, ext): + return ext.export_symbols + def get_ext_filename (self, ext_name): + if sys.platform == 'win32': + return ext_name + ".dll" + else: + return ext_name + ".so" + + # distutils.core.setup() is really meant for end-user + # interactive usage, because it eats most exceptions and + # turn them into SystemExits. Instead, we directly + # instantiate a Distribution, which also allows us to + # ignore unwanted features like config files. + extra_compile_args = [] + # ensure correct math on windows + if sys.platform == 'win32': + extra_compile_args.append('/Op') # get extra precision + if get_default_compiler() == 'unix': + old_version = False + try: + g = os.popen('gcc --version', 'r') + verinfo = g.read() + g.close() + except (OSError, IOError): + pass + else: + old_version = verinfo.startswith('2') + if not old_version: + extra_compile_args.extend(["-Wno-unused-label", + "-Wno-unused-variable"]) + attrs = { + 'name': "testmodule", + 'ext_modules': [ + Extension(modname, [str(cfile) for cfile in cfiles], + extra_compile_args=extra_compile_args, + **extension_options) + ], + 'script_name': 'setup.py', + 'script_args': ['-q', 'build_ext'], # don't remove 'build_ext' here + } + dist = Distribution(attrs) + # patch our own command obj into distutils + # because it does not have a facility to accept + # custom objects + cmdobj = build_shared_library(dist) + cmdobj.inplace = True + cmdobj.force = True + if (sys.platform == 'win32' + and sys.executable.lower().endswith('_d.exe')): + cmdobj.debug = True + dist.command_obj["build_ext"] = cmdobj + dist.have_run["build_ext"] = 0 + + if not dist.parse_command_line(): + raise ValueError, "distutils cmdline parse error" + dist.run_commands() + + def compile_c_module(cfiles, modbasename, eci, tmpdir=None): #try: # from distutils.log import set_threshold @@ -292,7 +414,6 @@ if tmpdir is None: tmpdir = udir.join("module_cache").ensure(dir=1) num = 0 - cfiles += eci.separate_module_files include_dirs = list(eci.include_dirs) include_dirs.append(py.path.local(pypydir).join('translator', 'c')) library_dirs = list(eci.library_dirs) @@ -335,77 +456,17 @@ cmd += ' -L%s' % dir os.system(cmd) else: - from distutils.dist import Distribution - from distutils.extension import Extension - from distutils.ccompiler import get_default_compiler - from distutils.command.build_ext import build_ext - - class build_shared_library(build_ext): - """ We build shared libraries, not python modules. - On windows, avoid to export the initXXX function, - and don't use a .pyd extension. """ - def get_export_symbols(self, ext): - return ext.export_symbols - def get_ext_filename (self, ext_name): - if sys.platform == 'win32': - return ext_name + ".dll" - else: - return ext_name + ".so" + extension_options=dict(include_dirs=include_dirs, + library_dirs=library_dirs, + libraries=list(libraries), + export_symbols=export_symbols, + extra_objects=eci.extra_objects, + ) saved_environ = os.environ.items() try: - # distutils.core.setup() is really meant for end-user - # interactive usage, because it eats most exceptions and - # turn them into SystemExits. Instead, we directly - # instantiate a Distribution, which also allows us to - # ignore unwanted features like config files. - extra_compile_args = [] - # ensure correct math on windows - if sys.platform == 'win32': - extra_compile_args.append('/Op') # get extra precision - if get_default_compiler() == 'unix': - old_version = False - try: - g = os.popen('gcc --version', 'r') - verinfo = g.read() - g.close() - except (OSError, IOError): - pass - else: - old_version = verinfo.startswith('2') - if not old_version: - extra_compile_args.extend(["-Wno-unused-label", - "-Wno-unused-variable"]) - attrs = { - 'name': "testmodule", - 'ext_modules': [ - Extension(modname, [str(cfile) for cfile in cfiles], - include_dirs=include_dirs, - library_dirs=library_dirs, - extra_compile_args=extra_compile_args, - libraries=list(libraries), - export_symbols=export_symbols, - ) - ], - 'script_name': 'setup.py', - 'script_args': ['-q', 'build_ext'], # don't remove 'build_ext' here - } - dist = Distribution(attrs) - # patch our own command obj into distutils - # because it does not have a facility to accept - # custom objects - cmdobj = build_shared_library(dist) - cmdobj.inplace = True - cmdobj.force = True - if (sys.platform == 'win32' - and sys.executable.lower().endswith('_d.exe')): - cmdobj.debug = True - dist.command_obj["build_ext"] = cmdobj - dist.have_run["build_ext"] = 0 - - if not dist.parse_command_line(): - raise ValueError, "distutils cmdline parse error" - dist.run_commands() + compile_shared_library(modname, cfiles, + extension_options) finally: for key, value in saved_environ: if os.environ.get(key) != value: @@ -574,7 +635,8 @@ linker_exe linker_so'''.split(): compiler.executables[c][0] = self.compiler_exe compiler.spawn = log_spawned_cmd(compiler.spawn) - objects = [] + + objects = list(self.eci.extra_objects) for cfile in self.cfilenames: cfile = py.path.local(cfile) old = cfile.dirpath().chdir() Modified: pypy/branch/build-external/pypy/translator/tool/test/test_cbuild.py ============================================================================== --- pypy/branch/build-external/pypy/translator/tool/test/test_cbuild.py (original) +++ pypy/branch/build-external/pypy/translator/tool/test/test_cbuild.py Thu May 29 19:04:20 2008 @@ -2,7 +2,7 @@ from pypy.tool.udir import udir from pypy.translator.tool.cbuild import build_executable, \ - ExternalCompilationInfo, compile_c_module + ExternalCompilationInfo, CompilationSet, compile_c_module from subprocess import Popen, PIPE, STDOUT def test_simple_executable(): @@ -92,19 +92,20 @@ assert e.pre_include_lines == ('1', '2', '3') def test_convert_sources_to_c_files(self): - eci = ExternalCompilationInfo( - separate_module_sources = ['xxx'], - separate_module_files = ['x.c'], + cs = CompilationSet( + ExternalCompilationInfo(), + sources = ['xxx'], + files = ['x.c'], ) cache_dir = udir.join('test_convert_sources').ensure(dir=1) - neweci = eci.convert_sources_to_files(cache_dir) - assert not neweci.separate_module_sources - res = neweci.separate_module_files + newcs = cs.convert_sources_to_files(cache_dir) + assert not newcs.sources + res = newcs.files assert len(res) == 2 assert res[0] == 'x.c' assert str(res[1]).startswith(str(cache_dir)) - e = ExternalCompilationInfo() - assert e.convert_sources_to_files() is e + cs = CompilationSet(ExternalCompilationInfo()) + assert cs.convert_sources_to_files() is cs def test_make_shared_lib(self): eci = ExternalCompilationInfo( From fijal at codespeak.net Thu May 29 19:16:54 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 29 May 2008 19:16:54 +0200 (CEST) Subject: [pypy-svn] r55405 - pypy/dist/pypy/module/__builtin__/test Message-ID: <20080529171654.BB2701684D3@codespeak.net> Author: fijal Date: Thu May 29 19:16:53 2008 New Revision: 55405 Modified: pypy/dist/pypy/module/__builtin__/test/test_import.py Log: A test for 55401 Modified: pypy/dist/pypy/module/__builtin__/test/test_import.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/test/test_import.py (original) +++ pypy/dist/pypy/module/__builtin__/test/test_import.py Thu May 29 19:16:53 2008 @@ -536,3 +536,32 @@ tried_imports[0][0] == "datetime" finally: sys.meta_path.pop() + + def test_path_hooks_leaking(self): + class Importer(object): + def find_module(self, fullname, path=None): + if fullname == "a": + return self + + def load_module(self, name): + return sys + + def importer_for_path(path): + if path == "xxx": + return Importer() + raise ImportError() + import sys + try: + sys.path_hooks.append(importer_for_path) + sys.path.insert(0, "yyy") + sys.path.insert(0, "xxx") + import a + try: + import b + except ImportError: + pass + assert sys.path_importer_cache['yyy'] is None + finally: + sys.path.pop(0) + sys.path.pop(0) + sys.path_hooks.pop() From fijal at codespeak.net Thu May 29 22:28:23 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 29 May 2008 22:28:23 +0200 (CEST) Subject: [pypy-svn] r55407 - pypy/branch/parser-complexity Message-ID: <20080529202823.200F71684D4@codespeak.net> Author: fijal Date: Thu May 29 22:28:21 2008 New Revision: 55407 Added: pypy/branch/parser-complexity/ - copied from r55405, pypy/dist/ Log: A branch to fight some wrong algorithmic complexity issues in parser From fijal at codespeak.net Thu May 29 22:43:56 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 29 May 2008 22:43:56 +0200 (CEST) Subject: [pypy-svn] r55408 - pypy/branch/parser-complexity/pypy/interpreter/astcompiler Message-ID: <20080529204356.B89341684C8@codespeak.net> Author: fijal Date: Thu May 29 22:43:53 2008 New Revision: 55408 Modified: pypy/branch/parser-complexity/pypy/interpreter/astcompiler/misc.py Log: This speeds up astcompiler quite a bit Modified: pypy/branch/parser-complexity/pypy/interpreter/astcompiler/misc.py ============================================================================== --- pypy/branch/parser-complexity/pypy/interpreter/astcompiler/misc.py (original) +++ pypy/branch/parser-complexity/pypy/interpreter/astcompiler/misc.py Thu May 29 22:43:53 2008 @@ -45,11 +45,31 @@ return "_%s%s" % (klass, name) +class Queue(object): + def __init__(self, item): + self.head = [item] + self.tail = [] + + def pop(self): + if self.head: + return self.head.pop() + else: + for i in range(len(self.tail)-1, -1, -1): + self.head.append(self.tail[i]) + self.tail = [] + return self.head.pop() + + def extend(self, items): + self.tail.extend(items) + + def nonempty(self): + return self.tail or self.head + def set_filename(filename, tree): """Set the filename attribute to filename on every node in tree""" - worklist = [tree] - while worklist: - node = worklist.pop(0) + worklist = Queue(tree) + while worklist.nonempty(): + node = worklist.pop() assert isinstance(node, ast.Node) node.filename = filename worklist.extend(node.getChildNodes()) From fijal at codespeak.net Thu May 29 22:58:51 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 29 May 2008 22:58:51 +0200 (CEST) Subject: [pypy-svn] r55409 - pypy/dist/pypy/interpreter/astcompiler Message-ID: <20080529205851.853701684C6@codespeak.net> Author: fijal Date: Thu May 29 22:58:50 2008 New Revision: 55409 Modified: pypy/dist/pypy/interpreter/astcompiler/misc.py Log: Port 55408 from parser-complexity branch. Improves a bit performance of attaching filename Modified: pypy/dist/pypy/interpreter/astcompiler/misc.py ============================================================================== --- pypy/dist/pypy/interpreter/astcompiler/misc.py (original) +++ pypy/dist/pypy/interpreter/astcompiler/misc.py Thu May 29 22:58:50 2008 @@ -45,11 +45,31 @@ return "_%s%s" % (klass, name) +class Queue(object): + def __init__(self, item): + self.head = [item] + self.tail = [] + + def pop(self): + if self.head: + return self.head.pop() + else: + for i in range(len(self.tail)-1, -1, -1): + self.head.append(self.tail[i]) + self.tail = [] + return self.head.pop() + + def extend(self, items): + self.tail.extend(items) + + def nonempty(self): + return self.tail or self.head + def set_filename(filename, tree): """Set the filename attribute to filename on every node in tree""" - worklist = [tree] - while worklist: - node = worklist.pop(0) + worklist = Queue(tree) + while worklist.nonempty(): + node = worklist.pop() assert isinstance(node, ast.Node) node.filename = filename worklist.extend(node.getChildNodes()) From fijal at codespeak.net Thu May 29 23:58:18 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Thu, 29 May 2008 23:58:18 +0200 (CEST) Subject: [pypy-svn] r55410 - pypy/dist/pypy/rlib/test Message-ID: <20080529215818.D0BCF1684C8@codespeak.net> Author: fijal Date: Thu May 29 23:58:16 2008 New Revision: 55410 Modified: pypy/dist/pypy/rlib/test/test_libffi.py Log: Skip this test on posix Modified: pypy/dist/pypy/rlib/test/test_libffi.py ============================================================================== --- pypy/dist/pypy/rlib/test/test_libffi.py (original) +++ pypy/dist/pypy/rlib/test/test_libffi.py Thu May 29 23:58:16 2008 @@ -362,6 +362,10 @@ assert not ALLOCATED class TestWin32Handles: + def setup_class(cls): + if sys.platform != 'win32': + py.test.skip("Win-only test") + def test_get_libc_handle(self): handle = get_libc_handle() print get_libc_name() From afa at codespeak.net Fri May 30 03:45:57 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 30 May 2008 03:45:57 +0200 (CEST) Subject: [pypy-svn] r55414 - in pypy/branch/build-external/pypy/translator: c c/test tool Message-ID: <20080530014557.784C11684EC@codespeak.net> Author: afa Date: Fri May 30 03:45:55 2008 New Revision: 55414 Modified: pypy/branch/build-external/pypy/translator/c/gc.py pypy/branch/build-external/pypy/translator/c/genc.py pypy/branch/build-external/pypy/translator/c/test/test_boehm.py pypy/branch/build-external/pypy/translator/tool/cbuild.py Log: pypy can not compile the boehm gc from sources. Modified: pypy/branch/build-external/pypy/translator/c/gc.py ============================================================================== --- pypy/branch/build-external/pypy/translator/c/gc.py (original) +++ pypy/branch/build-external/pypy/translator/c/gc.py Fri May 30 03:45:55 2008 @@ -7,6 +7,7 @@ from pypy.rpython.memory.gctransform import \ refcounting, boehm, framework, llvmgcroot, asmgcroot from pypy.rpython.lltypesystem import lltype, llmemory +from pypy.translator.tool.cbuild import ExternalCompilationInfo, CompilationSet class BasicGcPolicy(object): requires_stackless = False @@ -36,8 +37,8 @@ def struct_after_definition(self, defnode): return [] - def gc_libraries(self): - return [] + def compilation_info(self): + return ExternalCompilationInfo() def pre_pre_gc_code(self): # code that goes before include g_prerequisite.h gct = self.db.gctransformer @@ -184,10 +185,55 @@ def rtti_node_factory(self): return BoehmGcRuntimeTypeInfo_OpaqueNode - def gc_libraries(self): - if sys.platform == 'win32': - return ['gc_pypy'] - return ['gc'] + def compilation_info(self): + from pypy.translator.tool.cbuild import external_dir + + # Get source: + # http://www.hpl.hp.com/personal/Hans_Boehm/gc/gc_source/gc6.8.tar.gz + # extract it into the "dist/external" directory + gc_home = external_dir.join("gc6.8") + + if gc_home.check(dir=True): + from pypy.tool.udir import udir + udir.join('gc', 'gc.h').ensure() + udir.join('gc', 'gc.h').write('#include "%s/include/gc.h"' % gc_home) + + gc_eci = ExternalCompilationInfo( + include_dirs=[gc_home.join('include')], + compile_extra=['-DGC_WIN32_THREADS', '-DGC_NOT_DLL'], + libraries=['user32'], + ) + + cs = CompilationSet(gc_eci, + files=[gc_home.join(x) for x in + ['malloc.c', 'mallocx.c', 'alloc.c', + 'allchblk.c', 'new_hblk.c', + 'finalize.c', 'reclaim.c', + 'headers.c', 'obj_map.c', 'stubborn.c', + 'mark.c', 'mark_rts.c', 'blacklst.c', + 'misc.c', 'os_dep.c', 'mach_dep.c', + 'dyn_load.c', + 'win32_threads.c', + ]]) + + eci = ExternalCompilationInfo( + include_dirs=[udir], + compile_extra=['-DGC_WIN32_THREADS', '-DGC_NOT_DLL'], + extra_objects=cs.compile_objects(), + libraries=['user32'], + ) + + else: + if sys.platform == 'win32': + libraries = ['gc_pypy'], + else: + libraries = ['gc'] + + eci = ExternalCompilationInfo( + libraries=libraries, + ) + + return eci def pre_pre_gc_code(self): for line in BasicGcPolicy.pre_pre_gc_code(self): @@ -254,7 +300,6 @@ class NoneGcPolicy(BoehmGcPolicy): - gc_libraries = RefcountingGcPolicy.gc_libraries.im_func gc_startup_code = RefcountingGcPolicy.gc_startup_code.im_func Modified: pypy/branch/build-external/pypy/translator/c/genc.py ============================================================================== --- pypy/branch/build-external/pypy/translator/c/genc.py (original) +++ pypy/branch/build-external/pypy/translator/c/genc.py Fri May 30 03:45:55 2008 @@ -79,8 +79,7 @@ def collect_compilation_info(self, db): # we need a concrete gcpolicy to do this - self.eci = self.eci.merge(ExternalCompilationInfo( - libraries=db.gcpolicy.gc_libraries())) + self.eci = self.eci.merge(db.gcpolicy.compilation_info()) all = [] for node in self.db.globalcontainers(): Modified: pypy/branch/build-external/pypy/translator/c/test/test_boehm.py ============================================================================== --- pypy/branch/build-external/pypy/translator/c/test/test_boehm.py (original) +++ pypy/branch/build-external/pypy/translator/c/test/test_boehm.py Fri May 30 03:45:55 2008 @@ -7,7 +7,7 @@ from pypy import conftest def setup_module(mod): - if not check_boehm_presence(): + if not check_boehm_presence(noerr=False): py.test.skip("Boehm GC not present") class AbstractGCTestClass(object): Modified: pypy/branch/build-external/pypy/translator/tool/cbuild.py ============================================================================== --- pypy/branch/build-external/pypy/translator/tool/cbuild.py (original) +++ pypy/branch/build-external/pypy/translator/tool/cbuild.py Fri May 30 03:45:55 2008 @@ -293,6 +293,7 @@ try: objects = compiler.compile( files, + extra_preargs=list(self.eci.compile_extra), include_dirs=self.eci.include_dirs, ) objects = [str(py.path.local(o)) for o in objects] @@ -663,6 +664,7 @@ return str(compiler.outputfilename) def check_boehm_presence(noerr=True): + from pypy.translator.c.gc import BoehmGcPolicy from pypy.tool.udir import udir try: cfile = udir.join('check_boehm.c') @@ -672,14 +674,12 @@ #include int main() { + GC_malloc(10); return 0; } """) cfile.close() - if sys.platform == 'win32': - eci = ExternalCompilationInfo(libraries=['gc_pypy']) - else: - eci = ExternalCompilationInfo(libraries=['gc']) + eci = BoehmGcPolicy(db=None).compilation_info() build_executable([cfname], eci, noerr=noerr) except CompilationError: if noerr: From afa at codespeak.net Fri May 30 10:32:18 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 30 May 2008 10:32:18 +0200 (CEST) Subject: [pypy-svn] r55415 - pypy/branch/build-external/pypy/translator/c Message-ID: <20080530083218.8898A168070@codespeak.net> Author: afa Date: Fri May 30 10:32:14 2008 New Revision: 55415 Modified: pypy/branch/build-external/pypy/translator/c/gc.py Log: Correct indentation and a typo in the log message of the previous checkin: pypy can now compile the boehm gc from sources. * Modified: pypy/branch/build-external/pypy/translator/c/gc.py ============================================================================== --- pypy/branch/build-external/pypy/translator/c/gc.py (original) +++ pypy/branch/build-external/pypy/translator/c/gc.py Fri May 30 10:32:14 2008 @@ -225,7 +225,7 @@ else: if sys.platform == 'win32': - libraries = ['gc_pypy'], + libraries = ['gc_pypy'], else: libraries = ['gc'] From cami at codespeak.net Fri May 30 13:26:34 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Fri, 30 May 2008 13:26:34 +0200 (CEST) Subject: [pypy-svn] r55417 - pypy/dist/pypy/lang/gameboy Message-ID: <20080530112634.2C48916850F@codespeak.net> Author: cami Date: Fri May 30 13:26:32 2008 New Revision: 55417 Modified: pypy/dist/pypy/lang/gameboy/cartridge.py pypy/dist/pypy/lang/gameboy/cpu.py pypy/dist/pypy/lang/gameboy/gameboy.py pypy/dist/pypy/lang/gameboy/gameboyImplementation.py Log: updated gameboyimplementation to handle multiple keypresses fixed non-working esc-key for quitting the emulation Modified: pypy/dist/pypy/lang/gameboy/cartridge.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/cartridge.py (original) +++ pypy/dist/pypy/lang/gameboy/cartridge.py Fri May 30 13:26:32 2008 @@ -94,6 +94,7 @@ self.load_battery() self.mbc = self.create_bank_controller(self.get_memory_bank_type(), self.rom, self.ram, self.clock) + print self def check_rom(self): if not self.verify_header(): @@ -150,7 +151,7 @@ def get_checksum(self): return ((self.rom[constants.CHECKSUM_A_ADDRESS]) << 8) \ + (self.rom[constants.CHECKSUM_B_ADDRESS]) - + def has_battery(self): return has_cartridge_battery(self.get_memory_bank_type()) @@ -172,6 +173,12 @@ def create_bank_controller(self, type, rom, ram, clock_driver): return MEMORY_BANK_MAPPING[type](rom, ram, clock_driver) + + def __repr__(self): + return "Type=%s, Destination: %s ramSize: %sKB romSize: %sKB" % \ + (self.get_memory_bank_type(), self.get_destination_code(), + self.get_ram_size(), self.get_rom_size()/1024) + # ------------------------------------------------------------------------------ @@ -197,9 +204,9 @@ def load(self, cartridge_path): - cartridge_path = str(cartridge_path) - self.cartridge_file_path = cartridge_path - self.cartridge_stream = open_file_as_stream(cartridge_path) + cartridge_path = str(cartridge_path) + self.cartridge_file_path = cartridge_path + self.cartridge_stream = open_file_as_stream(cartridge_path) self.cartridge_file_contents = map_to_byte( self.cartridge_stream.readall()) self.load_battery(cartridge_path) @@ -386,9 +393,9 @@ elif address >= 0xA000 and address <= 0xBFFF and self.ram_enable: self.ram[self.ram_bank + (address & 0x1FFF)] = data else: - #return - raise InvalidMemoryAccessException("MBC 1Invalid memory Access address: %s" - % hex(address)) + return + #raise InvalidMemoryAccessException("MBC 1Invalid memory Access address: %s" + # % hex(address)) def write_rom_bank_1(self, address, data): if (data & 0x1F) == 0: Modified: pypy/dist/pypy/lang/gameboy/cpu.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/cpu.py (original) +++ pypy/dist/pypy/lang/gameboy/cpu.py Fri May 30 13:26:32 2008 @@ -365,7 +365,7 @@ def fetch_execute(self): opCode = self.fetch() - #print " fetch exe:", hex(opCode), " " + print " fetch exe:", hex(opCode), " " #, FETCH_EXECUTE_OP_CODES[opCode].__name__ self.last_fetch_execute_op_code = opCode FETCH_EXECUTE_OP_CODES[opCode](self) @@ -568,10 +568,10 @@ self.f.z_flag_compare(self.a.get(), reset=True) def inc_double_register(self, doubleRegister): - self.inc(doubleRegister.get, doubleRegister.set) + doubleRegister.set((doubleRegister.get() + 1) & 0xFF) def dec_double_register(self, doubleRegister): - self.dec(doubleRegister.get, doubleRegister.set) + doubleRegister.set((doubleRegister.get() - 1) & 0xFF) def inc(self, getCaller, setCaller): # 1 cycle Modified: pypy/dist/pypy/lang/gameboy/gameboy.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/gameboy.py (original) +++ pypy/dist/pypy/lang/gameboy/gameboy.py Fri May 30 13:26:32 2008 @@ -78,7 +78,7 @@ self.video.reset() self.sound.reset() self.cpu.set_rom(self.cartridge_manager.get_rom()) - self.draw_logo() + #self.draw_logo() def get_cycles(self): return min(min(min(min( self.video.get_cycles(), self.serial.get_cycles()), @@ -202,5 +202,5 @@ for tile in range(0, 12): self.video.write(0x9904 + tile, tile + 1) self.video.write(0x9924 + tile, tile + 13) - self.video.write(0x9905 + 12, 25) + Modified: pypy/dist/pypy/lang/gameboy/gameboyImplementation.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/gameboyImplementation.py (original) +++ pypy/dist/pypy/lang/gameboy/gameboyImplementation.py Fri May 30 13:26:32 2008 @@ -32,15 +32,17 @@ def mainLoop(self): - self.reset() + #self.reset() try: - while True: - if self.poll_event(): + isRunning = True + while isRunning: + while self.poll_event(): if self.check_for_escape(): - break + isRunning = False + break self.joypad_driver.update(self.event) self.emulate(constants.GAMEBOY_CLOCK >> 2) - RSDL.Delay(10) + #RSDL.Delay(1) finally: lltype.free(self.event, flavor='raw') RSDL.Quit() @@ -80,15 +82,15 @@ RSDL.Flip(self.screen) def draw_pixels(self): - str = "" + #str = "" for y in range(self.height): - str += "\n" + #str += "\n" for x in range(self.width): - if y%2 == 0 or True: - px = self.get_pixel_color(x, y) - str += ["#", "%", "+", " ", " "][px] - #RSDL_helper.set_pixel(self.screen, x, y, self.pixel_map(x, y)) - print str; + #if y%2 == 0 or True: + # px = self.get_pixel_color(x, y) + # str += ["#", "%", "+", " ", " "][px] + RSDL_helper.set_pixel(self.screen, x, y, self.pixel_map(x, y)) + #print str; def pixel_map(self, x, y): return [0xFFFFFF, 0xCCCCCC, 0x666666, 0x000000][self.get_pixel_color(x, y)] From arigo at codespeak.net Fri May 30 13:47:04 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 30 May 2008 13:47:04 +0200 (CEST) Subject: [pypy-svn] r55418 - pypy/dist/pypy/tool Message-ID: <20080530114704.C772F168506@codespeak.net> Author: arigo Date: Fri May 30 13:47:03 2008 New Revision: 55418 Modified: pypy/dist/pypy/tool/gcc_cache.py Log: Remove unused imports. Modified: pypy/dist/pypy/tool/gcc_cache.py ============================================================================== --- pypy/dist/pypy/tool/gcc_cache.py (original) +++ pypy/dist/pypy/tool/gcc_cache.py Fri May 30 13:47:03 2008 @@ -5,8 +5,6 @@ from pypy.translator.tool.cbuild import CompilationError import md5 import py -import distutils -import distutils.errors cache_dir_root = py.path.local(pypydir).join('_cache').ensure(dir=1) From arigo at codespeak.net Fri May 30 13:59:59 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 30 May 2008 13:59:59 +0200 (CEST) Subject: [pypy-svn] r55419 - pypy/dist/pypy/translator/c Message-ID: <20080530115959.3A567168454@codespeak.net> Author: arigo Date: Fri May 30 13:59:57 2008 New Revision: 55419 Modified: pypy/dist/pypy/translator/c/genc.py Log: A slightly safer "make clean". Modified: pypy/dist/pypy/translator/c/genc.py ============================================================================== --- pypy/dist/pypy/translator/c/genc.py (original) +++ pypy/dist/pypy/translator/c/genc.py Fri May 30 13:59:57 2008 @@ -892,7 +892,7 @@ \t$(PYPYDIR)/translator/c/gcc/trackgcroot.py $(GCMAPFILES) > $@ || (rm -f $@ && exit 1) clean: -\trm -f $(OBJECTS) $(TARGET) $(GCMAPFILES) ../*/*.gc?? +\trm -f $(OBJECTS) $(TARGET) $(GCMAPFILES) *.gc?? ../module_cache/*.gc?? clean_noprof: \trm -f $(OBJECTS) $(TARGET) $(GCMAPFILES) From arigo at codespeak.net Fri May 30 14:03:40 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 30 May 2008 14:03:40 +0200 (CEST) Subject: [pypy-svn] r55420 - pypy/dist/pypy/config Message-ID: <20080530120340.C551A168454@codespeak.net> Author: arigo Date: Fri May 30 14:03:39 2008 New Revision: 55420 Modified: pypy/dist/pypy/config/config.py Log: Print the pending warnings before exiting translate.py via an optparse.OptionValueError. Modified: pypy/dist/pypy/config/config.py ============================================================================== --- pypy/dist/pypy/config/config.py (original) +++ pypy/dist/pypy/config/config.py Fri May 30 14:03:39 2008 @@ -520,6 +520,12 @@ value = self.convert_from_cmdline(value) self.config.setoption(self.option._name, value, who='cmdline') except ConfigError, e: + # This OptionValueError is going to exit the translate.py process. + # Now is the last chance to print the warnings, which might give + # more information... hack. + import sys + for warning in self.config.get_warnings(): + print >> sys.stderr, warning raise optparse.OptionValueError(e.args[0]) def help_default(self): From arigo at codespeak.net Fri May 30 14:16:13 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 30 May 2008 14:16:13 +0200 (CEST) Subject: [pypy-svn] r55421 - pypy/dist/pypy/doc Message-ID: <20080530121613.D70F6168506@codespeak.net> Author: arigo Date: Fri May 30 14:16:12 2008 New Revision: 55421 Modified: pypy/dist/pypy/doc/getting-started.txt Log: Write down some typical Debian Linux packages that are known to be required for a PyPy translation. Modified: pypy/dist/pypy/doc/getting-started.txt ============================================================================== --- pypy/dist/pypy/doc/getting-started.txt (original) +++ pypy/dist/pypy/doc/getting-started.txt Fri May 30 14:16:12 2008 @@ -580,6 +580,11 @@ cd pypy/translator/goal python translate.py --gc=hybrid --thread targetpypystandalone.py --allworkingmodules --faassen +Dependencies: this will compile all supported built-in modules, some of +which have external dependencies. On a Debian Linux, for example, you +need to install the following packages: a full C compiler like gcc; +``python-dev``; ``libffi-dev, libz-dev, libbz2-dev``. + This whole process will take some time and quite a lot of memory (around 1GB). It creates an executable ``pypy-c`` in the current directory. The ``--gc=hybrid`` option means that the ``pypy-c`` will use our own From arigo at codespeak.net Fri May 30 14:20:21 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 30 May 2008 14:20:21 +0200 (CEST) Subject: [pypy-svn] r55422 - pypy/dist/pypy/doc Message-ID: <20080530122021.B6B32168506@codespeak.net> Author: arigo Date: Fri May 30 14:20:20 2008 New Revision: 55422 Modified: pypy/dist/pypy/doc/getting-started.txt Log: Mention the need for ctypes (thanks \3TATUK) Modified: pypy/dist/pypy/doc/getting-started.txt ============================================================================== --- pypy/dist/pypy/doc/getting-started.txt (original) +++ pypy/dist/pypy/doc/getting-started.txt Fri May 30 14:20:20 2008 @@ -583,7 +583,7 @@ Dependencies: this will compile all supported built-in modules, some of which have external dependencies. On a Debian Linux, for example, you need to install the following packages: a full C compiler like gcc; -``python-dev``; ``libffi-dev, libz-dev, libbz2-dev``. +``python-dev, python-ctypes``; ``libffi-dev, libz-dev, libbz2-dev``. This whole process will take some time and quite a lot of memory (around 1GB). It creates an executable ``pypy-c`` in the current directory. From arigo at codespeak.net Fri May 30 15:48:37 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 30 May 2008 15:48:37 +0200 (CEST) Subject: [pypy-svn] r55423 - pypy/dist/pypy/doc Message-ID: <20080530134837.73BA51684D2@codespeak.net> Author: arigo Date: Fri May 30 15:48:34 2008 New Revision: 55423 Modified: pypy/dist/pypy/doc/getting-started.txt Log: Need a curses library too. Modified: pypy/dist/pypy/doc/getting-started.txt ============================================================================== --- pypy/dist/pypy/doc/getting-started.txt (original) +++ pypy/dist/pypy/doc/getting-started.txt Fri May 30 15:48:34 2008 @@ -583,7 +583,8 @@ Dependencies: this will compile all supported built-in modules, some of which have external dependencies. On a Debian Linux, for example, you need to install the following packages: a full C compiler like gcc; -``python-dev, python-ctypes``; ``libffi-dev, libz-dev, libbz2-dev``. +``python-dev, python-ctypes``; ``libffi-dev, libz-dev, libbz2-dev, +libncurses-dev``. This whole process will take some time and quite a lot of memory (around 1GB). It creates an executable ``pypy-c`` in the current directory. From arigo at codespeak.net Fri May 30 16:18:47 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 30 May 2008 16:18:47 +0200 (CEST) Subject: [pypy-svn] r55424 - pypy/dist/pypy/doc/discussion Message-ID: <20080530141847.0591B168511@codespeak.net> Author: arigo Date: Fri May 30 16:18:42 2008 New Revision: 55424 Removed: pypy/dist/pypy/doc/discussion/standalone-howto.txt Log: Sorry, this is really more confusing than helpful. From arigo at codespeak.net Fri May 30 16:33:25 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 30 May 2008 16:33:25 +0200 (CEST) Subject: [pypy-svn] r55425 - pypy/dist/pypy/doc Message-ID: <20080530143325.E3F851684EA@codespeak.net> Author: arigo Date: Fri May 30 16:33:23 2008 New Revision: 55425 Modified: pypy/dist/pypy/doc/download.txt pypy/dist/pypy/doc/getting-started.txt pypy/dist/pypy/doc/redirections Log: * discourage people from using the 1.0 release more strongly. * redirect from standalone-howto to a FAQ entry. Modified: pypy/dist/pypy/doc/download.txt ============================================================================== --- pypy/dist/pypy/doc/download.txt (original) +++ pypy/dist/pypy/doc/download.txt Fri May 30 16:33:23 2008 @@ -2,6 +2,13 @@ Download one of the following release files: ============================================= +:warning: + + the 1.0 release is out of date. We strongly recommend that you + use the latest stable version. See `getting started`_. + +.. _`getting started`: getting-started.html#get-via-subversion + PyPy 1.0 Sources: ----------------- Modified: pypy/dist/pypy/doc/getting-started.txt ============================================================================== --- pypy/dist/pypy/doc/getting-started.txt (original) +++ pypy/dist/pypy/doc/getting-started.txt Fri May 30 16:33:23 2008 @@ -26,29 +26,35 @@ ============== .. _gettingpypy: +.. _`latest stable version via subversion`: +.. _`get via Subversion`: -Downloading & running the PyPy 1.0 release --------------------------------------------- +Svn-check out & run the latest PyPy as a two-liner +-------------------------------------------------- -*Note: the 1.0 release is out of date. We strongly recommend that you -use the latest stable version* (which you can `get via Subversion`_). +If you want to play with the stable development PyPy version +you can check it out from the repository using subversion. +(Here are `old links`_ to the PyPy release 1.0 -- but don't +use it, it is too far out of date.) + +.. _`old links`: download.html + +Download and install subversion_ if you don't already have it. We have +some `help on installing subversion`_ for PyPy. Then you can issue on +the command line (DOS box or terminal):: -Download one of the following release files: + svn co http://codespeak.net/svn/pypy/dist pypy-dist -*pypy-1.0* - - * `pypy-1.0.0.tar.bz2`_ (sources, unix line endings) or - * `pypy-1.0.0.tar.gz`_ (sources, unix line endings) or - * `pypy-1.0.0.zip`_ (sources, windows line-endings) or - * `pypy-1.0.0-win32.zip`_ (precompiled executables for windows) - * or get the `latest stable version via subversion`_. - -After unpacking the source downloads you can change to the -``pypy-1.0.0`` directory and execute the following command line:: +This will create a directory named ``pypy-dist``, and will get you the PyPy +source in ``pypy-dist/pypy`` and documentation files in +``pypy-dist/pypy/doc``. - python pypy/bin/py.py +After checkout you can get a PyPy interpreter via:: -This will give you a PyPy prompt, i.e. a very compliant Python + python pypy-dist/pypy/bin/py.py + +have fun :-) +This gives you a PyPy prompt, i.e. a very compliant Python interpreter implemented in Python. PyPy passes around `98% of CPythons core language regression tests`_. Because this invocation of PyPy still runs on top of CPython, it runs around 2000 times slower @@ -58,48 +64,13 @@ is required to import our version of ctypes). This is probably not something you want to play with for too long, -though, as it is really slow. -Since the 0.7.0 release it is possible to use PyPy to `translate +though, as it is really slow. Instead, you should use PyPy to `translate itself to lower level languages`_ after which it runs standalone, is not dependant on CPython anymore and becomes faster (within the same speed magnitude as CPython itself). -If you are using the precompiled Windows executables, please look -at the included ``README.txt`` on how to start already translated -interpreters. Note that the examples in the html documentation generally -assume that you have a py.py; with precompiled binaries, you need to -pick one with the matching features compiled in. - .. _`98% of CPythons core language regression tests`: http://www2.openend.se/~pedronis/pypy-c-test/allworkingmodules/summary.html -.. _`pypy-1.0.0.tar.bz2`: http://codespeak.net/download/pypy/pypy-1.0.0.tar.bz2 -.. _`pypy-1.0.0.zip`: http://codespeak.net/download/pypy/pypy-1.0.0.zip -.. _`pypy-1.0.0.tar.gz`: http://codespeak.net/download/pypy/pypy-1.0.0.tar.gz -.. _`pypy-1.0.0-win32.zip`: http://codespeak.net/download/pypy/pypy-1.0.0-win32.zip - -.. _`latest stable version via subversion`: -.. _`get via Subversion`: - -Svn-check out & run the latest PyPy as a two-liner --------------------------------------------------- - -If you want to play with the stable development PyPy version -you can check it out from the repository using subversion. Download -and install subversion_ if you don't already have it. Then you can -issue on the command line (DOS box or terminal):: - - svn co http://codespeak.net/svn/pypy/dist pypy-dist - -This will create a directory named ``pypy-dist``, and will get you the PyPy -source in ``pypy-dist/pypy`` and documentation files in -``pypy-dist/pypy/doc``. - -After checkout you can get a PyPy interpreter via:: - - python pypy-dist/pypy/bin/py.py - -have fun :-) -We have some `help on installing subversion`_ for PyPy. Have a look at `interesting starting points`_ for some guidance on how to continue. Modified: pypy/dist/pypy/doc/redirections ============================================================================== --- pypy/dist/pypy/doc/redirections (original) +++ pypy/dist/pypy/doc/redirections Fri May 30 16:33:23 2008 @@ -4,5 +4,6 @@ 'news.html': 'home.html', 'contact.html': 'home.html', 'jit.html': 'jit/index.html', + 'standalone-howto.html': 'faq.html#can-pypy-compile-normal-python-programs', } From afa at codespeak.net Fri May 30 17:36:45 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 30 May 2008 17:36:45 +0200 (CEST) Subject: [pypy-svn] r55426 - in pypy/branch/build-external/pypy: module/rctime module/rctime/test rpython/lltypesystem rpython/module rpython/module/test Message-ID: <20080530153645.07CD5168504@codespeak.net> Author: afa Date: Fri May 30 17:36:42 2008 New Revision: 55426 Modified: pypy/branch/build-external/pypy/module/rctime/__init__.py pypy/branch/build-external/pypy/module/rctime/interp_time.py pypy/branch/build-external/pypy/module/rctime/test/test_rctime.py pypy/branch/build-external/pypy/rpython/lltypesystem/rffi.py pypy/branch/build-external/pypy/rpython/module/ll_os.py pypy/branch/build-external/pypy/rpython/module/ll_time.py pypy/branch/build-external/pypy/rpython/module/test/test_ll_os.py Log: Adapt time functions to win32 and Visual 2005 (vs 8.0): time_t is a 64bit type, and functions are exported with modified names: _time64, _localtime64. Also port the timezone variables from ctypes to rffi. Modified: pypy/branch/build-external/pypy/module/rctime/__init__.py ============================================================================== --- pypy/branch/build-external/pypy/module/rctime/__init__.py (original) +++ pypy/branch/build-external/pypy/module/rctime/__init__.py Fri May 30 17:36:42 2008 @@ -19,15 +19,13 @@ 'mktime': 'interp_time.mktime', 'strftime': 'interp_time.strftime', 'sleep' : 'interp_time.sleep', + 'tzset' : 'interp_time.tzset', } def buildloaders(cls): from pypy.module.rctime import interp_time import os - if os.name == "posix": - Module.interpleveldefs['tzset'] = 'interp_time.tzset' - # this machinery is needed to expose constants # that have to be initialized one time only Modified: pypy/branch/build-external/pypy/module/rctime/interp_time.py ============================================================================== --- pypy/branch/build-external/pypy/module/rctime/interp_time.py (original) +++ pypy/branch/build-external/pypy/module/rctime/interp_time.py Fri May 30 17:36:42 2008 @@ -27,7 +27,7 @@ time_t = platform.SimpleType("time_t", rffi.LONG) size_t = platform.SimpleType("size_t", rffi.LONG) has_gettimeofday = platform.Has('gettimeofday') - + if _POSIX: calling_conv = 'c' CConfig.timeval = platform.Struct("struct timeval", @@ -61,6 +61,18 @@ if _POSIX: cConfig.timeval.__name__ = "_timeval" timeval = cConfig.timeval + +if _WIN: + def getter(typ, name): + func, _ = rffi.CExternVariable( + typ, name, + CConfig._compilation_info_, + readonly=True) + return func + + get_timezone = getter(rffi.LONG, "_timezone") + get_daylight = getter(rffi.LONG, "_daylight") + get_tzname = getter(rffi.CCHARPP, "tzname") CLOCKS_PER_SEC = cConfig.CLOCKS_PER_SEC clock_t = cConfig.clock_t @@ -73,15 +85,27 @@ c_gettimeofday = external('gettimeofday', [rffi.VOIDP, rffi.VOIDP], rffi.INT) TIME_TP = rffi.CArrayPtr(time_t) TM_P = lltype.Ptr(tm) + +def m(name): + """Name mangling, for VS8.0 which exports 32bit and 64bit versions + under different names + """ + if _WIN and rffi.sizeof(time_t) == 8: + return '_' + name + '64' + else: + return name + c_clock = external('clock', [TIME_TP], clock_t) -c_time = external('time', [TIME_TP], time_t) -c_ctime = external('ctime', [TIME_TP], rffi.CCHARP) -c_gmtime = external('gmtime', [TIME_TP], TM_P) -c_mktime = external('mktime', [TM_P], time_t) +c_time = external(m('time'), [TIME_TP], time_t) +c_ctime = external(m('ctime'), [TIME_TP], rffi.CCHARP) +c_gmtime = external(m('gmtime'), [TIME_TP], TM_P) +c_mktime = external(m('mktime'), [TM_P], time_t) c_asctime = external('asctime', [TM_P], rffi.CCHARP) -c_localtime = external('localtime', [TIME_TP], TM_P) +c_localtime = external(m('localtime'), [TIME_TP], TM_P) if _POSIX: c_tzset = external('tzset', [], lltype.Void) +if _WIN: + c_tzset = external('_tzset', [], lltype.Void) c_strftime = external('strftime', [rffi.CCHARP, size_t, rffi.CCHARP, TM_P], size_t) @@ -92,20 +116,12 @@ timezone = daylight = altzone = 0 tzname = ["", ""] - # pypy cant' use in_dll to access global exported variables - # so we can't compute these attributes - - # if _WIN: - # cdll.msvcrt._tzset() - # - # timezone = c_long.in_dll(cdll.msvcrt, "_timezone").value - # if hasattr(cdll.msvcrt, "altzone"): - # altzone = c_long.in_dll(cdll.msvcrt, "altzone").value - # else: - # altzone = timezone - 3600 - # daylight = c_long.in_dll(cdll.msvcrt, "_daylight").value - # tzname = _tzname_t.in_dll(cdll.msvcrt, "_tzname") - # tzname = (tzname.tzname_0, tzname.tzname_1) + if _WIN: + timezone = get_timezone() + altzone = timezone - 3600 + daylight = get_daylight() + tznames = get_tzname() + tzname = [rffi.charp2str(tznames[0]), rffi.charp2str(tznames[1])] if _POSIX: YEAR = (365 * 24 + 6) * 3600 @@ -143,9 +159,13 @@ errno = rposix.get_errno() return os.strerror(errno) -def sleep(secs): - pytime.sleep(secs) -sleep.unwrap_spec = [float] +def sleep(space, secs): + try: + pytime.sleep(secs) + except OverflowError: + raise OperationError(space.w_OverflowError, + space.wrap("sleep length is too large")) +sleep.unwrap_spec = [ObjSpace, float] def _get_module_object(space, obj_name): w_module = space.getbuiltinmodule('time') @@ -164,10 +184,11 @@ else: seconds = space.float_w(w_seconds) try: - return ovfcheck_float_to_int(seconds) + ovfcheck_float_to_int(seconds) except OverflowError: raise OperationError(space.w_ValueError, space.wrap("time argument too large")) + return rffi.r_time_t(seconds) def _tm_to_tuple(space, t): time_tuple = [] @@ -189,7 +210,7 @@ def _gettmarg(space, w_tup, allowNone=True): if allowNone and space.is_w(w_tup, space.w_None): # default to the current local time - tt = int(pytime.time()) + tt = rffi.r_time_t(pytime.time()) t_ref = lltype.malloc(TIME_TP.TO, 1, flavor='raw') t_ref[0] = tt pbuf = c_localtime(t_ref) @@ -364,30 +385,29 @@ return space.wrap(float(tt)) mktime.unwrap_spec = [ObjSpace, W_Root] -if _POSIX: - def tzset(space): - """tzset() - - Initialize, or reinitialize, the local timezone to the value stored in - os.environ['TZ']. The TZ environment variable should be specified in - standard Unix timezone format as documented in the tzset man page - (eg. 'US/Eastern', 'Europe/Amsterdam'). Unknown timezones will silently - fall back to UTC. If the TZ environment variable is not set, the local - timezone is set to the systems best guess of wallclock time. - Changing the TZ environment variable without calling tzset *may* change - the local timezone used by methods such as localtime, but this behaviour - should not be relied on""" +def tzset(space): + """tzset() - c_tzset() - - # reset timezone, altzone, daylight and tzname - timezone, daylight, tzname, altzone = _init_timezone() - _set_module_object(space, "timezone", space.wrap(timezone)) - _set_module_object(space, 'daylight', space.wrap(daylight)) - tzname_w = [space.wrap(tzname[0]), space.wrap(tzname[1])] - _set_module_object(space, 'tzname', space.newtuple(tzname_w)) - _set_module_object(space, 'altzone', space.wrap(altzone)) - tzset.unwrap_spec = [ObjSpace] + Initialize, or reinitialize, the local timezone to the value stored in + os.environ['TZ']. The TZ environment variable should be specified in + standard Unix timezone format as documented in the tzset man page + (eg. 'US/Eastern', 'Europe/Amsterdam'). Unknown timezones will silently + fall back to UTC. If the TZ environment variable is not set, the local + timezone is set to the systems best guess of wallclock time. + Changing the TZ environment variable without calling tzset *may* change + the local timezone used by methods such as localtime, but this behaviour + should not be relied on""" + + c_tzset() + + # reset timezone, altzone, daylight and tzname + timezone, daylight, tzname, altzone = _init_timezone() + _set_module_object(space, "timezone", space.wrap(timezone)) + _set_module_object(space, 'daylight', space.wrap(daylight)) + tzname_w = [space.wrap(tzname[0]), space.wrap(tzname[1])] + _set_module_object(space, 'tzname', space.newtuple(tzname_w)) + _set_module_object(space, 'altzone', space.wrap(altzone)) +tzset.unwrap_spec = [ObjSpace] def strftime(space, format, w_tup=None): """strftime(format[, tuple]) -> string Modified: pypy/branch/build-external/pypy/module/rctime/test/test_rctime.py ============================================================================== --- pypy/branch/build-external/pypy/module/rctime/test/test_rctime.py (original) +++ pypy/branch/build-external/pypy/module/rctime/test/test_rctime.py Fri May 30 17:36:42 2008 @@ -76,6 +76,7 @@ def test_mktime(self): import time as rctime + import os raises(TypeError, rctime.mktime, "foo") raises(TypeError, rctime.mktime, None) raises(TypeError, rctime.mktime, (1, 2)) @@ -93,7 +94,8 @@ ltime = list(ltime) ltime[0] = 67 ltime = tuple(ltime) - raises(OverflowError, rctime.mktime, ltime) + if os.name != "nt": # time_t may be 64bit + raises(OverflowError, rctime.mktime, ltime) ltime = list(ltime) ltime[0] = 100 Modified: pypy/branch/build-external/pypy/rpython/lltypesystem/rffi.py ============================================================================== --- pypy/branch/build-external/pypy/rpython/lltypesystem/rffi.py (original) +++ pypy/branch/build-external/pypy/rpython/lltypesystem/rffi.py Fri May 30 17:36:42 2008 @@ -273,7 +273,8 @@ for name in (_name, 'unsigned ' + _name): TYPES.append(name) TYPES += ['signed char', 'unsigned char', - 'long long', 'unsigned long long', 'size_t'] + 'long long', 'unsigned long long', + 'size_t', 'time_t'] if os.name != 'nt': TYPES.append('mode_t') TYPES.append('pid_t') @@ -378,7 +379,7 @@ return lltype.Ptr(COpaque(*args, **kwds)) def CExternVariable(TYPE, name, eci, _CConstantClass=CConstant, - sandboxsafe=False): + sandboxsafe=False, readonly=False): """Return a pair of functions - a getter and a setter - to access the given global C variable. """ @@ -408,12 +409,17 @@ if sys.platform != 'win32': lines.append('extern %s %s;' % (c_type, name)) lines.append(c_getter) - lines.append(c_setter) + + symbols = [getter_name] + if not readonly: + lines.append(c_setter) + symbols.append(setter_name) + sources = ('\n'.join(lines),) new_eci = eci.merge(ExternalCompilationInfo( separate_module_sources = sources, post_include_lines = [getter_prototype, setter_prototype], - export_symbols = [getter_name, setter_name], + export_symbols = symbols, )) getter = llexternal(getter_name, [], TYPE, compilation_info=new_eci, Modified: pypy/branch/build-external/pypy/rpython/module/ll_os.py ============================================================================== --- pypy/branch/build-external/pypy/rpython/module/ll_os.py (original) +++ pypy/branch/build-external/pypy/rpython/module/ll_os.py Fri May 30 17:36:42 2008 @@ -262,8 +262,8 @@ # we only have utime(), which does not allow sub-second resolution def os_utime_platform(path, actime, modtime): l_utimbuf = lltype.malloc(UTIMBUFP.TO, flavor='raw') - l_utimbuf.c_actime = int(actime) - l_utimbuf.c_modtime = int(modtime) + l_utimbuf.c_actime = rffi.r_time_t(actime) + l_utimbuf.c_modtime = rffi.r_time_t(modtime) error = os_utime(path, l_utimbuf) lltype.free(l_utimbuf, flavor='raw') return error Modified: pypy/branch/build-external/pypy/rpython/module/ll_time.py ============================================================================== --- pypy/branch/build-external/pypy/rpython/module/ll_time.py (original) +++ pypy/branch/build-external/pypy/rpython/module/ll_time.py Fri May 30 17:36:42 2008 @@ -11,8 +11,8 @@ from pypy.rlib import rposix from pypy.translator.tool.cbuild import ExternalCompilationInfo -if sys.platform.startswith('win'): - includes = ['time.h', 'windows.h'] +if sys.platform == 'win32': + includes = ['time.h', 'sys/timeb.h'] else: includes = ['sys/time.h', 'time.h', 'errno.h', 'sys/select.h', 'sys/types.h', 'unistd.h', 'sys/timeb.h'] @@ -23,11 +23,13 @@ includes=includes ) CLOCK_T = platform.SimpleType('clock_t', rffi.INT) - TIMEVAL = platform.Struct('struct timeval', [('tv_sec', rffi.INT), - ('tv_usec', rffi.INT)]) + if sys.platform != 'win32': + TIMEVAL = platform.Struct('struct timeval', [('tv_sec', rffi.INT), + ('tv_usec', rffi.INT)]) TIME_T = platform.SimpleType('time_t', rffi.INT) HAVE_GETTIMEOFDAY = platform.Has('gettimeofday') HAVE_FTIME = platform.Has('ftime') + HAVE_FTIME64 = platform.Has('_ftime64') class CConfigForFTime: _compilation_info_ = ExternalCompilationInfo(includes=['sys/timeb.h']) @@ -49,7 +51,8 @@ self.CLOCKS_PER_SEC = 1000000 else: self.CLOCKS_PER_SEC = self.CLK_TCK - self.TIMEVALP = lltype.Ptr(self.TIMEVAL) + if sys.platform != 'win32': + self.TIMEVALP = lltype.Ptr(self.TIMEVAL) @registering(time.time) def register_time_time(self): @@ -70,15 +73,26 @@ else: c_gettimeofday = None - if self.HAVE_FTIME: + if self.HAVE_FTIME or self.HAVE_FTIME64: self.configure(CConfigForFTime) - c_ftime = self.llexternal('ftime', [lltype.Ptr(self.TIMEB)], + + if sys.platform == 'win32' and rffi.sizeof(self.TIME_T) == 8: + name = '_ftime64' + else: + name = 'ftime' + + c_ftime = self.llexternal(name, [lltype.Ptr(self.TIMEB)], lltype.Void, _nowrapper=True, threadsafe=False) else: c_ftime = None # to not confuse the flow space - c_time = self.llexternal('time', [rffi.VOIDP], self.TIME_T, + if sys.platform == 'win32' and rffi.sizeof(self.TIME_T) == 8: + name = '_time64' + else: + name = 'time' + + c_time = self.llexternal(name, [rffi.VOIDP], self.TIME_T, _nowrapper=True, threadsafe=False) def time_time_llimpl(): Modified: pypy/branch/build-external/pypy/rpython/module/test/test_ll_os.py ============================================================================== --- pypy/branch/build-external/pypy/rpython/module/test/test_ll_os.py (original) +++ pypy/branch/build-external/pypy/rpython/module/test/test_ll_os.py Fri May 30 17:36:42 2008 @@ -56,7 +56,7 @@ def test_system(): filename = str(udir.join('test_system.txt')) - arg = 'python -c "print 1+1" > %s' % filename + arg = '%s -c "print 1+1" > %s' % (sys.executable, filename) data = getllimpl(os.system)(arg) assert data == 0 assert file(filename).read().strip() == '2' From fijal at codespeak.net Fri May 30 17:42:36 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 30 May 2008 17:42:36 +0200 (CEST) Subject: [pypy-svn] r55427 - pypy/dist/pypy/lib Message-ID: <20080530154236.5F771168504@codespeak.net> Author: fijal Date: Fri May 30 17:42:33 2008 New Revision: 55427 Added: pypy/dist/pypy/lib/py (contents, props changed) Log: Add a symlink to py library Added: pypy/dist/pypy/lib/py ============================================================================== --- (empty file) +++ pypy/dist/pypy/lib/py Fri May 30 17:42:33 2008 @@ -0,0 +1 @@ +link ../../py \ No newline at end of file From afa at codespeak.net Fri May 30 18:20:58 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 30 May 2008 18:20:58 +0200 (CEST) Subject: [pypy-svn] r55428 - pypy/branch/build-external/pypy/module/rctime Message-ID: <20080530162058.2AFD51684D3@codespeak.net> Author: afa Date: Fri May 30 18:20:56 2008 New Revision: 55428 Modified: pypy/branch/build-external/pypy/module/rctime/__init__.py pypy/branch/build-external/pypy/module/rctime/interp_time.py Log: initialize timezone info when the module loads, not when the module is translated Modified: pypy/branch/build-external/pypy/module/rctime/__init__.py ============================================================================== --- pypy/branch/build-external/pypy/module/rctime/__init__.py (original) +++ pypy/branch/build-external/pypy/module/rctime/__init__.py Fri May 30 18:20:56 2008 @@ -24,20 +24,19 @@ def buildloaders(cls): from pypy.module.rctime import interp_time - import os # this machinery is needed to expose constants # that have to be initialized one time only Module.interpleveldefs["accept2dyear"] = 'space.wrap(%r)' %\ interp_time._init_accept2dyear() - - timezone, daylight, tzname, altzone = interp_time._init_timezone() - Module.interpleveldefs['timezone'] = 'space.wrap(%r)' % timezone - Module.interpleveldefs['daylight'] = 'space.wrap(%r)' % daylight + + Module.interpleveldefs['timezone'] = 'space.wrap(0)' + Module.interpleveldefs['daylight'] = 'space.wrap(0)' Module.interpleveldefs['tzname'] = \ - 'space.newlist([space.wrap(%r), space.wrap(%r)])' % tuple(tzname) - Module.interpleveldefs['altzone'] = 'space.wrap(%r)' % altzone + 'space.newlist([space.wrap(""), space.wrap("")])' + Module.interpleveldefs['altzone'] = 'space.wrap(0)' + super(Module, cls).buildloaders() buildloaders = classmethod(buildloaders) @@ -46,3 +45,7 @@ '__doc__': 'app_time.__doc__', 'strptime': 'app_time.strptime', } + + def startup(self, space): + from pypy.module.rctime import interp_time + interp_time.tzset(space) Modified: pypy/branch/build-external/pypy/module/rctime/interp_time.py ============================================================================== --- pypy/branch/build-external/pypy/module/rctime/interp_time.py (original) +++ pypy/branch/build-external/pypy/module/rctime/interp_time.py Fri May 30 18:20:56 2008 @@ -405,7 +405,7 @@ _set_module_object(space, "timezone", space.wrap(timezone)) _set_module_object(space, 'daylight', space.wrap(daylight)) tzname_w = [space.wrap(tzname[0]), space.wrap(tzname[1])] - _set_module_object(space, 'tzname', space.newtuple(tzname_w)) + _set_module_object(space, 'tzname', space.newlist(tzname_w)) _set_module_object(space, 'altzone', space.wrap(altzone)) tzset.unwrap_spec = [ObjSpace] From fijal at codespeak.net Fri May 30 20:55:29 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 30 May 2008 20:55:29 +0200 (CEST) Subject: [pypy-svn] r55430 - pypy/django/tests Message-ID: <20080530185529.C37C41684EB@codespeak.net> Author: fijal Date: Fri May 30 20:55:26 2008 New Revision: 55430 Added: pypy/django/tests/old_conftest.py - copied unchanged from r55278, pypy/django/tests/conftest.py Removed: pypy/django/tests/conftest.py Log: Rename conftest to avoid confusion next time. This DOES NOT work. From fijal at codespeak.net Fri May 30 21:01:07 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 30 May 2008 21:01:07 +0200 (CEST) Subject: [pypy-svn] r55431 - pypy/django/tests/regressiontests/dispatch/tests Message-ID: <20080530190107.77AA6168512@codespeak.net> Author: fijal Date: Fri May 30 21:01:06 2008 New Revision: 55431 Modified: pypy/django/tests/regressiontests/dispatch/tests/test_dispatcher.py Log: Carefully insert gc.collects() for tests to pass Modified: pypy/django/tests/regressiontests/dispatch/tests/test_dispatcher.py ============================================================================== --- pypy/django/tests/regressiontests/dispatch/tests/test_dispatcher.py (original) +++ pypy/django/tests/regressiontests/dispatch/tests/test_dispatcher.py Fri May 30 21:01:06 2008 @@ -22,10 +22,11 @@ def setUp(self): # track the initial state, since it's possible that others have bleed receivers in + gc.collect() self.sendersBack = copy.copy(dispatcher.sendersBack) self.connections = copy.copy(dispatcher.connections) self.senders = copy.copy(dispatcher.senders) - + def _testIsClean(self): """Assert that everything has been cleaned up automatically""" self.assertEqual(dispatcher.sendersBack, self.sendersBack) @@ -87,10 +88,10 @@ connect(a.a, signal, b) expected = [] del a + gc.collect() result = send('this',b, a=b) self.assertEqual(result, expected) self.assertEqual(list(getAllReceivers(b,signal)), []) - gc.collect() self._testIsClean() def testGarbageCollectedObj(self): @@ -103,10 +104,10 @@ connect(a, signal, b) expected = [] del a + gc.collect() result = send('this',b, a=b) self.assertEqual(result, expected) self.assertEqual(list(getAllReceivers(b,signal)), []) - gc.collect() self._testIsClean() From fijal at codespeak.net Fri May 30 21:29:34 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 30 May 2008 21:29:34 +0200 (CEST) Subject: [pypy-svn] r55432 - pypy/dist/pypy/module/gc Message-ID: <20080530192934.506ED168532@codespeak.net> Author: fijal Date: Fri May 30 21:29:31 2008 New Revision: 55432 Modified: pypy/dist/pypy/module/gc/__init__.py Log: Add a gc.garbage, always empty, in order if someone would ever like to introspect it. Modified: pypy/dist/pypy/module/gc/__init__.py ============================================================================== --- pypy/dist/pypy/module/gc/__init__.py (original) +++ pypy/dist/pypy/module/gc/__init__.py Fri May 30 21:29:31 2008 @@ -11,4 +11,5 @@ 'enable_finalizers': 'interp_gc.enable_finalizers', 'disable_finalizers': 'interp_gc.disable_finalizers', 'estimate_heap_size': 'interp_gc.estimate_heap_size', + 'garbage' : 'space.newlist([])', } From afa at codespeak.net Fri May 30 21:42:57 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 30 May 2008 21:42:57 +0200 (CEST) Subject: [pypy-svn] r55433 - pypy/branch/build-external/pypy/rlib Message-ID: <20080530194257.E798B168502@codespeak.net> Author: afa Date: Fri May 30 21:42:53 2008 New Revision: 55433 Modified: pypy/branch/build-external/pypy/rlib/rmmap.py Log: rmmap: No need to use ctypes when configuring the module. Use "configure" and compiled code instead. Modified: pypy/branch/build-external/pypy/rlib/rmmap.py ============================================================================== --- pypy/branch/build-external/pypy/rlib/rmmap.py (original) +++ pypy/branch/build-external/pypy/rlib/rmmap.py Fri May 30 21:42:53 2008 @@ -40,6 +40,28 @@ if _MS_WINDOWS: LPSECURITY_ATTRIBUTES = rffi_platform.SimpleType("LPSECURITY_ATTRIBUTES", rffi.CCHARP) +class CConfigForPagesize: + if _POSIX: + code = "int get_page_size() { return getpagesize(); }" + if _MS_WINDOWS: + code = """ + int get_page_size() { + SYSTEM_INFO si; + GetSystemInfo(&si); + return si.dwPageSize; + }""" + _compilation_info_ = ExternalCompilationInfo( + includes=includes, + pre_include_lines=['#ifndef _GNU_SOURCE', + '#define _GNU_SOURCE', + '#endif'], + separate_module_sources=[code], + ) + PAGESIZE = rffi_platform.ConstantInteger("get_page_size()") + +cConfig = rffi_platform.configure(CConfigForPagesize) +PAGESIZE = cConfig['PAGESIZE'] + constants = {} if _POSIX: # constants, look in sys/mman.h and platform docs for the meaning @@ -108,8 +130,6 @@ if has_mremap: c_mremap = external('mremap', [PTR, size_t, size_t, rffi.ULONG], PTR) - _get_page_size = external('getpagesize', [], rffi.INT) - def _get_error_no(): return rposix.get_errno() @@ -178,14 +198,6 @@ GetLastError = winexternal('GetLastError', [], DWORD) - def _get_page_size(): - try: - si = rffi.make(SYSTEM_INFO) - GetSystemInfo(si) - return int(si.c_dwPageSize) - finally: - lltype.free(si, flavor="raw") - def _get_file_size(handle): # XXX use native Windows types like WORD high_ref = lltype.malloc(LPDWORD.TO, 1, flavor='raw') @@ -214,7 +226,6 @@ NULL_HANDLE = rffi.cast(HANDLE, 0) INVALID_HANDLE = rffi.cast(HANDLE, -1) -PAGESIZE = _get_page_size() NULL = lltype.nullptr(PTR.TO) NODATA = lltype.nullptr(PTR.TO) From afa at codespeak.net Fri May 30 22:30:15 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 30 May 2008 22:30:15 +0200 (CEST) Subject: [pypy-svn] r55434 - pypy/branch/build-external/pypy/module/signal Message-ID: <20080530203015.5C7F3398001@codespeak.net> Author: afa Date: Fri May 30 22:30:14 2008 New Revision: 55434 Modified: pypy/branch/build-external/pypy/module/signal/__init__.py Log: Someone, please check: The "signal" module used to install its hook very early, when the MixedModule was instantiated: it was active during all the translation phase, and the pypysig_poll() function was called many times! Now we activate it only on module startup, that is, (I hope) when the translated pypy-c starts. This may be the last remaining usage of ctypes during translation. Modified: pypy/branch/build-external/pypy/module/signal/__init__.py ============================================================================== --- pypy/branch/build-external/pypy/module/signal/__init__.py (original) +++ pypy/branch/build-external/pypy/module/signal/__init__.py Fri May 30 22:30:14 2008 @@ -23,9 +23,7 @@ super(Module, cls).buildloaders() buildloaders = classmethod(buildloaders) - def __init__(self, space, *args): - "NOT_RPYTHON" + def startup(self, space): from pypy.module.signal.interp_signal import CheckSignalAction - MixedModule.__init__(self, space, *args) # add the signal-checking callback as an action on the space space.pending_actions.append(CheckSignalAction(space)) From arigo at codespeak.net Fri May 30 22:35:30 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 30 May 2008 22:35:30 +0200 (CEST) Subject: [pypy-svn] r55435 - pypy/dist/pypy/objspace/flow Message-ID: <20080530203530.ABC60398001@codespeak.net> Author: arigo Date: Fri May 30 22:35:27 2008 New Revision: 55435 Modified: pypy/dist/pypy/objspace/flow/flowcontext.py Log: Avoid this pop(0) by using a deque. Modified: pypy/dist/pypy/objspace/flow/flowcontext.py ============================================================================== --- pypy/dist/pypy/objspace/flow/flowcontext.py (original) +++ pypy/dist/pypy/objspace/flow/flowcontext.py Fri May 30 22:35:27 2008 @@ -1,3 +1,7 @@ +try: + import collections +except ImportError: + from pypy.lib import collections # python < 2.4 from pypy.interpreter.executioncontext import ExecutionContext from pypy.interpreter.error import OperationError from pypy.interpreter import pyframe @@ -209,7 +213,7 @@ #for joinpoint in code.getjoinpoints(): # self.joinpoints[joinpoint] = [] # list of blocks initialblock = SpamBlock(FrameState(frame).copy()) - self.pendingblocks = [initialblock] + self.pendingblocks = collections.deque([initialblock]) self.graph = FunctionGraph(name or code.co_name, initialblock) make_link = Link # overridable for transition tracking @@ -251,7 +255,7 @@ def build_flow(self): while self.pendingblocks: - block = self.pendingblocks.pop(0) + block = self.pendingblocks.popleft() frame = self.create_frame() try: self.recorder = block.patchframe(frame) From fijal at codespeak.net Fri May 30 22:57:43 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 30 May 2008 22:57:43 +0200 (CEST) Subject: [pypy-svn] r55436 - pypy/dist/pypy/tool Message-ID: <20080530205743.459A2168454@codespeak.net> Author: fijal Date: Fri May 30 22:57:39 2008 New Revision: 55436 Modified: pypy/dist/pypy/tool/tls.py Log: Really use tlsobject Modified: pypy/dist/pypy/tool/tls.py ============================================================================== --- pypy/dist/pypy/tool/tls.py (original) +++ pypy/dist/pypy/tool/tls.py Fri May 30 22:57:39 2008 @@ -1,26 +1,8 @@ -##"""Thread-local storage.""" -## -##try: -## from thread import _local as tlsobject -##except ImportError: # Python < 2.4 -## -## # XXX needs a real object whose attributes are visible only in -## # the thread that reads/writes them. -## -## import autopath, os -## filename = os.path.join(os.path.dirname(autopath.pypydir), -## 'lib-python', '2.4.1', '_threading_local.py') -## glob = {'__name__': '_threading_local'} -## execfile(filename, glob) -## tlsobject = glob['local'] -## del glob, filename +"""Thread-local storage.""" - - - -class tlsobject(object): - """Storage that is NOT THREAD-LOCAL AT ALL because we don't really need it - at the moment, and it has a performance impact -- a minor one on top of 2.4, - and an extreme one on top of 2.3 :-((((( - """ +try: + from thread import _local as tlsobject +except ImportError: + class tlsobject(object): + pass From fijal at codespeak.net Fri May 30 22:59:50 2008 From: fijal at codespeak.net (fijal at codespeak.net) Date: Fri, 30 May 2008 22:59:50 +0200 (CEST) Subject: [pypy-svn] r55437 - pypy/dist/pypy/objspace/flow Message-ID: <20080530205950.21FC1168454@codespeak.net> Author: fijal Date: Fri May 30 22:59:48 2008 New Revision: 55437 Modified: pypy/dist/pypy/objspace/flow/flowcontext.py Log: Kill 2.3-only logic Modified: pypy/dist/pypy/objspace/flow/flowcontext.py ============================================================================== --- pypy/dist/pypy/objspace/flow/flowcontext.py (original) +++ pypy/dist/pypy/objspace/flow/flowcontext.py Fri May 30 22:59:48 2008 @@ -1,7 +1,4 @@ -try: - import collections -except ImportError: - from pypy.lib import collections # python < 2.4 +import collections from pypy.interpreter.executioncontext import ExecutionContext from pypy.interpreter.error import OperationError from pypy.interpreter import pyframe From afa at codespeak.net Fri May 30 23:42:57 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Fri, 30 May 2008 23:42:57 +0200 (CEST) Subject: [pypy-svn] r55438 - pypy/branch/build-external/pypy/module/_rawffi Message-ID: <20080530214257.73CC61684F9@codespeak.net> Author: afa Date: Fri May 30 23:42:51 2008 New Revision: 55438 Modified: pypy/branch/build-external/pypy/module/_rawffi/callback.py Log: This was already corrected in trunk/ Modified: pypy/branch/build-external/pypy/module/_rawffi/callback.py ============================================================================== --- pypy/branch/build-external/pypy/module/_rawffi/callback.py (original) +++ pypy/branch/build-external/pypy/module/_rawffi/callback.py Fri May 30 23:42:51 2008 @@ -33,7 +33,7 @@ w_args = space.newlist([space.wrap(rffi.cast(rffi.UINT, ll_args[i])) for i in range(len(argtypes))]) w_res = space.call(w_callable, w_args) - if callback_ptr.res != 'O': # don't return void + if callback_ptr.result != 'O': # don't return void unwrap_value(space, push_elem, ll_res, 0, letter2tp(space, callback_ptr.result), w_res) except OperationError, e: From cami at codespeak.net Sat May 31 09:52:45 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Sat, 31 May 2008 09:52:45 +0200 (CEST) Subject: [pypy-svn] r55440 - in pypy/dist/pypy/lang/gameboy: . test Message-ID: <20080531075245.6BF84168511@codespeak.net> Author: cami Date: Sat May 31 09:52:43 2008 New Revision: 55440 Added: pypy/dist/pypy/lang/gameboy/test/test_cpu_2.py Modified: pypy/dist/pypy/lang/gameboy/cpu.py pypy/dist/pypy/lang/gameboy/test/test_joypad.py Log: added more flag tests Modified: pypy/dist/pypy/lang/gameboy/cpu.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/cpu.py (original) +++ pypy/dist/pypy/lang/gameboy/cpu.py Sat May 31 09:52:43 2008 @@ -188,7 +188,7 @@ """ PyGIRL GameBoy (TM) Emulator - Central Unit ProcessOR (Sharp LR35902 CPU) + Central Unit Processor_a (Sharp LR35902 CPU) """ def __init__(self, interrupt, memory): assert isinstance(interrupt, Interrupt) @@ -365,7 +365,7 @@ def fetch_execute(self): opCode = self.fetch() - print " fetch exe:", hex(opCode), " " + #print " fetch exe:", hex(opCode), " " #, FETCH_EXECUTE_OP_CODES[opCode].__name__ self.last_fetch_execute_op_code = opCode FETCH_EXECUTE_OP_CODES[opCode](self) @@ -456,8 +456,9 @@ def call(self, address, use_cycles=True): # 4 cycles - self.push(self.pc.get_hi(use_cycles), use_cycles) # 2 cycles - self.push(self.pc.get_lo(use_cycles), use_cycles) # 2 cycles + self.push_double_register(self.pc, use_cycles) + #self.push(self.pc.get_hi(use_cycles), use_cycles) # 2 cycles + #self.push(self.pc.get_lo(use_cycles), use_cycles) # 2 cycles self.pc.set(address, use_cycles=use_cycles) # 1 cycle if use_cycles: self.cycles += 1 @@ -480,7 +481,6 @@ def add_a(self, getCaller, setCaller=None): # ALU, 1 cycle added = (self.a.get() + getCaller.get()) & 0xFF - self.f.reset() self.f.z_flag_compare(added) self.f.h_flag_compare(added, self.a.get(), inverted=True) self.f.c_flag = (added < self.a.get()) @@ -496,20 +496,16 @@ self.hl.set(added) self.cycles -= 1 - def add_with_carry(self, getCaller, setCaller=None): + def add_a_with_carry(self, getCaller, setCaller=None): # 1 cycle data = getCaller.get() - s = self.a.get() + data - if self.f.c_flag: - s +=1 + s = self.a.get() + data + int(self.f.c_flag) self.carry_flag_finish(s,data) - def subtract_with_carry(self, getCaller, setCaller=None): + def subtract_with_carry_a(self, getCaller, setCaller=None): # 1 cycle data = getCaller.get() - s = self.a.get() - data - if self.f.c_flag: - s -= 1 + s = self.a.get() - data - int(self.f.c_flag) self.carry_flag_finish(s, data) self.f.n_flag = True @@ -518,16 +514,15 @@ # set the hflag if the 0x10 bit was affected if ((s ^ self.a.get() ^ data) & 0x10) != 0: self.f.h_flag = True - if s >= 0x100: - self.f.c_flag= True + self.f.c_flag = (s >= 0x100 or s < 0) self.f.z_flag_compare(s) - self.a.set(s) # 1 cycle + self.a.set(s & 0xFF) # 1 cycle def subtract_a(self, getCaller, setCaller=None): # 1 cycle self.compare_a(getCaller) # 1 cycle self.a.sub(getCaller.get(use_cycles=False), False) - + def fetch_subtract_a(self): data = self.fetch() # 1 cycle @@ -552,27 +547,37 @@ #self.f.c_flag_compare(data, self.a.get()) self.f.h_flag_compare(data, self.a.get()) - def AND(self, getCaller, setCaller=None): + def and_a(self, getCaller, setCaller=None): # 1 cycle self.a.set(self.a.get() & getCaller.get()) # 1 cycle - self.f.z_flag_compare(self.a.get(), reset=True) + self.f.reset() + self.f.z_flag_compare(self.a.get()) + self.f.h_flag = True - def XOR(self, getCaller, setCaller=None): + def xor_a(self, getCaller, setCaller=None): # 1 cycle self.a.set( self.a.get() ^ getCaller.get()) # 1 cycle self.f.z_flag_compare(self.a.get(), reset=True) - def OR(self, getCaller, setCaller=None): + def or_a(self, getCaller, setCaller=None): # 1 cycle self.a.set(self.a.get() | getCaller.get()) # 1 cycle self.f.z_flag_compare(self.a.get(), reset=True) - def inc_double_register(self, doubleRegister): - doubleRegister.set((doubleRegister.get() + 1) & 0xFF) - - def dec_double_register(self, doubleRegister): - doubleRegister.set((doubleRegister.get() - 1) & 0xFF) - + def inc_double_register(self, register): + # INC rr + register.inc() + + def dec_double_register(self, register): + # DEC rr + register.dec() + +# def inc_double_register(self, doubleRegister): +# doubleRegister.set((doubleRegister.get() + 1) & 0xFF) +# +# def dec_double_register(self, doubleRegister): +# doubleRegister.set((doubleRegister.get() - 1) & 0xFF) + def inc(self, getCaller, setCaller): # 1 cycle data = (getCaller.get() + 1) & 0xFF @@ -593,8 +598,8 @@ def rotate_left_circular(self, getCaller, setCaller): # RLC 1 cycle data = getCaller.get() - s = (data << 1) + (data >> 7) - self.flags_and_setter_finish(s, setCaller, 0x80) + s = ((data << 1) & 0xFF) + ((data & 0x80) >> 7) + self.flags_and_setter_finish(s, data, setCaller, 0x80) #self.cycles -= 1 def rotate_left_circular_a(self): @@ -604,10 +609,9 @@ def rotate_left(self, getCaller, setCaller): # 1 cycle - s = (getCaller.get() << 1) & 0xFF - if self.f.c_flag: - s += 0x01 - self.flags_and_setter_finish(s, setCaller, 0x80) # 1 cycle + data = getCaller.get() + s = ((data & 0x7F) << 1) + int(self.f.c_flag) + self.flags_and_setter_finish(s, data, setCaller, 0x80) # 1 cycle def rotate_left_a(self): # RLA 1 cycle @@ -618,7 +622,7 @@ data = getCaller.get() # RRC 1 cycle s = (data >> 1) + ((data & 0x01) << 7) - self.flags_and_setter_finish(s, setCaller) # 1 cycle + self.flags_and_setter_finish(s, data, setCaller) # 1 cycle def rotate_right_circular_a(self): # RRCA 1 cycle @@ -627,38 +631,41 @@ def rotate_right(self, getCaller, setCaller): # 1 cycle - s = (getCaller.get() >> 1) + data = getCaller.get() + s = (data >> 1) if self.f.c_flag: - s += 0x08 - self.flags_and_setter_finish(s, setCaller) # 1 cycle + s += 0x80 + self.flags_and_setter_finish(s, data, setCaller) # 1 cycle def rotate_right_a(self): # RRA 1 cycle self.rotate_right(RegisterCallWrapper(self.a), RegisterCallWrapper(self.a)) - + def shift_left_arithmetic(self, getCaller, setCaller): # 2 cycles - s = (getCaller.get() << 1) & 0xFF - self.flags_and_setter_finish(s, setCaller, 0x80) # 1 cycle + data = getCaller.get() + s = (data << 1) & 0xFF + self.flags_and_setter_finish(s, data, setCaller, 0x80) # 1 cycle def shift_right_arithmetic(self, getCaller, setCaller): data = getCaller.get() # 1 cycle s = (data >> 1) + (data & 0x80) - self.flags_and_setter_finish(s, setCaller) # 1 cycle + self.flags_and_setter_finish(s, data, setCaller) # 1 cycle def shift_word_right_logical(self, getCaller, setCaller): # 2 cycles - s = (getCaller.get() >> 1) - self.flags_and_setter_finish(s, setCaller) # 2 cycles - - def flags_and_setter_finish(self, s, setCaller, compare_and=0x01): + data = getCaller.get() + s = (data >> 1) + self.flags_and_setter_finish(s, data, setCaller) # 2 cycles + + def flags_and_setter_finish(self, s, data, setCaller, compare_and=0x01): # 2 cycles s &= 0xFF self.f.reset() self.f.z_flag_compare(s) - self.f.c_flag_compare(s, compare_and) + self.f.c_flag_compare(data, compare_and) setCaller.set(s) # 1 cycle def swap(self, getCaller, setCaller): @@ -668,6 +675,7 @@ self.f.z_flag_compare(s, reset=True) setCaller.set(s) + def test_bit(self, getCaller, setCaller, n): # 2 cycles self.f.partial_reset(keep_c=True) @@ -768,7 +776,7 @@ self.f.n_flag = True self.f.h_flag = True - def decimal_adjust_accumulator(self): + def decimal_adjust_a(self): # DAA 1 cycle delta = 0 if self.is_h(): @@ -790,14 +798,6 @@ self.f.c_flag = True self.f.z_flag_compare(self.a.get()) - def inc_double_register(self, register): - # INC rr - register.inc() - - def dec_double_register(self, register): - # DEC rr - register.dec() - def increment_sp_by_fetch(self): # ADD SP,nn 4 cycles self.sp.set(self.get_fetchadded_sp()) # 1+1 cycle @@ -828,7 +828,7 @@ def process_2_complement(self, value): # check if the left most bit is set if (value >> 7) == 1: - return -((~value) & 0xFF)-1 + return -((~value) & 0xFF) - 1 else : return value @@ -845,7 +845,7 @@ # NOP 1 cycle self.cycles -= 1 - def unconditional_jump(self): + def jump(self): # JP nnnn, 4 cycles self.pc.set(self.fetch_double_address()) # 1+2 cycles self.cycles -= 1 @@ -853,11 +853,11 @@ def conditional_jump(self, cc): # JP cc,nnnn 3,4 cycles if cc: - self.unconditional_jump() # 4 cycles + self.jump() # 4 cycles else: self.pc.add(2) # 3 cycles - def relative_unconditional_jump(self): + def relative_jump(self): # JR +nn, 3 cycles #pc = pc & 0xFF00 + ((pc & 0x00FF) + add) & 0xFF self.pc.add(self.process_2_complement(self.fetch())) # 3 + 1 cycles @@ -866,7 +866,7 @@ def relative_conditional_jump(self, cc): # JR cc,+nn, 2,3 cycles if cc: - self.relative_unconditional_jump() # 3 cycles + self.relative_jump() # 3 cycles else: self.pc.inc() # 2 cycles @@ -1076,11 +1076,11 @@ # OPCODE TABLES --------------------------------------------------------------- # Table with one to one mapping of simple OP Codes -FIRST_ORDER_OP_CODES = [ +FIRST_or_aDER_OP_CODES = [ (0x00, CPU.nop), (0x08, CPU.load_mem_sp), (0x10, CPU.stop), - (0x18, CPU.relative_unconditional_jump), + (0x18, CPU.relative_jump), (0x02, CPU.write_a_at_bc_address), (0x12, CPU.write_a_at_de_address), (0x22, CPU.load_and_increment_hli_a), @@ -1093,7 +1093,7 @@ (0x0F, CPU.rotate_right_circular_a), (0x17, CPU.rotate_left_a), (0x1F, CPU.rotate_right_a), - (0x27, CPU.decimal_adjust_accumulator), + (0x27, CPU.decimal_adjust_a), (0x2F, CPU.complement_a), (0x37, CPU.set_carry_flag), (0x3F, CPU.complement_carry_flag), @@ -1104,7 +1104,7 @@ (0xEA, CPU.store_a_at_fetched_address), (0xF2, CPU.store_expanded_c_in_a), (0xFA, CPU.store_fetched_memory_in_a), - (0xC3, CPU.unconditional_jump), + (0xC3, CPU.jump), (0xC9, CPU.ret), (0xD9, CPU.return_form_interrupt), (0xDD, CPU.debug), @@ -1117,12 +1117,12 @@ (0xCB, CPU.fetch_execute), (0xCD, CPU.unconditional_call), (0xC6, lambda s: CPU.add_a(s, CPUFetchCaller(s))), - (0xCE, lambda s: CPU.add_with_carry(s, CPUFetchCaller(s))), + (0xCE, lambda s: CPU.add_a_with_carry(s, CPUFetchCaller(s))), (0xD6, CPU.fetch_subtract_a), - (0xDE, lambda s: CPU.subtract_with_carry(s, CPUFetchCaller(s))), - (0xE6, lambda s: CPU.AND(s, CPUFetchCaller(s))), - (0xEE, lambda s: CPU.XOR(s, CPUFetchCaller(s))), - (0xF6, lambda s: CPU.OR(s, CPUFetchCaller(s))), + (0xDE, lambda s: CPU.subtract_with_carry_a(s, CPUFetchCaller(s))), + (0xE6, lambda s: CPU.and_a(s, CPUFetchCaller(s))), + (0xEE, lambda s: CPU.xor_a(s, CPUFetchCaller(s))), + (0xF6, lambda s: CPU.or_a(s, CPUFetchCaller(s))), (0xFE, lambda s: CPU.compare_a(s, CPUFetchCaller(s))), (0xC7, lambda s: CPU.restart(s, 0x00)), (0xCF, lambda s: CPU.restart(s, 0x08)), @@ -1140,12 +1140,12 @@ (0x05, 0x08, CPU.dec), (0x06, 0x08, CPU.load_fetch_register), (0x80, 0x01, CPU.add_a), - (0x88, 0x01, CPU.add_with_carry), + (0x88, 0x01, CPU.add_a_with_carry), (0x90, 0x01, CPU.subtract_a), - (0x98, 0x01, CPU.subtract_with_carry), - (0xA0, 0x01, CPU.AND), - (0xA8, 0x01, CPU.XOR), - (0xB0, 0x01, CPU.OR), + (0x98, 0x01, CPU.subtract_with_carry_a), + (0xA0, 0x01, CPU.and_a), + (0xA8, 0x01, CPU.xor_a), + (0xB0, 0x01, CPU.or_a), (0xB8, 0x01, CPU.compare_a), (0x06, 0x08, CPU.fetch_load) ] @@ -1169,7 +1169,7 @@ (0xC5, 0x10, CPU.push_double_register, REGISTER_SET_B) ] # Table for Second Order OPCodes: (startAddress, delta, method, [args]) -SECOND_ORDER_REGISTER_GROUP_OP_CODES = [ +SECOND_or_aDER_REGISTER_GROUP_OP_CODES = [ (0x00, 0x01, CPU.rotate_left_circular), (0x08, 0x01, CPU.rotate_right_circular), (0x10, 0x01, CPU.rotate_left), @@ -1185,11 +1185,11 @@ # RAW OPCODE TABLE INITIALIZATION ---------------------------------------------- -FIRST_ORDER_OP_CODES += create_register_op_codes(REGISTER_OP_CODES) -FIRST_ORDER_OP_CODES += create_group_op_codes(REGISTER_GROUP_OP_CODES) -FIRST_ORDER_OP_CODES += create_load_group_op_codes() -SECOND_ORDER_OP_CODES = create_group_op_codes(SECOND_ORDER_REGISTER_GROUP_OP_CODES) +FIRST_or_aDER_OP_CODES += create_register_op_codes(REGISTER_OP_CODES) +FIRST_or_aDER_OP_CODES += create_group_op_codes(REGISTER_GROUP_OP_CODES) +FIRST_or_aDER_OP_CODES += create_load_group_op_codes() +SECOND_or_aDER_OP_CODES = create_group_op_codes(SECOND_or_aDER_REGISTER_GROUP_OP_CODES) -OP_CODES = initialize_op_code_table(FIRST_ORDER_OP_CODES) -FETCH_EXECUTE_OP_CODES = initialize_op_code_table(SECOND_ORDER_OP_CODES) +OP_CODES = initialize_op_code_table(FIRST_or_aDER_OP_CODES) +FETCH_EXECUTE_OP_CODES = initialize_op_code_table(SECOND_or_aDER_OP_CODES) Added: pypy/dist/pypy/lang/gameboy/test/test_cpu_2.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/lang/gameboy/test/test_cpu_2.py Sat May 31 09:52:43 2008 @@ -0,0 +1,842 @@ +import py +from pypy.lang.gameboy.cpu import * +from pypy.lang.gameboy.ram import * +from pypy.lang.gameboy import * +from pypy.lang.gameboy.interrupt import * + +# Helpers --------------------------------------------------------------------- + +class Memory(object): + def __init__(self): + self.memory = [0xFF]*0xFFFFF + + def write(self, address, data): + self.memory[address] = data + + def read(self, address): + return self.memory[address] + +global TEST_CPU + +TEST_CPU = None +def get_cpu(new=False): + if new: + cpu = CPU(Interrupt(), Memory()) + cpu.set_rom([0]*0xFFFF); + return cpu + global TEST_CPU + if TEST_CPU == None: + TEST_CPU = get_cpu(True) + TEST_CPU.reset() + return TEST_CPU + +def assert_default_registers(cpu, a=constants.RESET_A, bc=constants.RESET_BC,\ + de=constants.RESET_DE, f=constants.RESET_F,\ + hl=constants.RESET_HL, sp=constants.RESET_SP,\ + pc=constants.RESET_PC): + return assert_registers(cpu, a, bc, de, f, hl, sp, pc) + +def assert_registers(cpu, a=None, bc=None, de=None, f=None, hl=None, sp=None, pc=None): + if a is not None: + assert cpu.a.get() == a, "Register a is %s but should be %s" % (hex(cpu.a.get()), hex(a)) + if bc is not None: + assert cpu.bc.get() == bc, "Register bc is %s but should be %s" % (hex(cpu.bc.get()), hex(bc)) + if de is not None: + assert cpu.de.get() == de, "Register de is %s but should be %s" % (hex(cpu.de.get()),hex(de)) + if f is not None: + assert cpu.f.get() == f, "Register f is %s but should be %s" % (hex(cpu.f.get()),hex(f)) + if hl is not None: + assert cpu.hl.get() == hl, "Register hl is %s but should be %s" % (hex(cpu.hl.get()), hex(hl)) + if sp is not None: + assert cpu.sp.get() == sp, "Register sp is %s but should be %s" % (hex(cpu.sp.get()), hex(sp)) + if pc is not None: + assert cpu.pc.get() == pc, "Register pc is %s but should be %s" % (hex(cpu.pc.get()), hex(pc)) + + +def assert_defaults(cpu, z=True, n=False, h=False, c=False, p=False, s=False): + assert_flags(cpu, z, n, h, c, p, s) + +def assert_flags(cpu, z=None, n=None, h=None, c=None, p=None, s=None): + if z is not None: + assert cpu.f.z_flag == z, "Z-Flag is %s but should be %s" % (cpu.f.z_flag, z) + if n is not None: + assert cpu.f.n_flag == n, "N-Flag is %s but should be %s" % (cpu.f.n_flag, n) + if h is not None: + assert cpu.f.h_flag == h, "H-Flag is %s but should be %s" % (cpu.f.h_flag, h) + if c is not None: + assert cpu.f.c_flag == c, "C-Flag is %s but should be %s" % (cpu.f.c_flag, c) + if p is not None: + assert cpu.f.p_flag == p, "P-Flag is %s but should be %s" % (cpu.f.p_flag, p) + if s is not None: + assert cpu.f.s_flag == s, "S-Flag is %s but should be %s" % (cpu.f.s_flag, s) + +def prepare_for_double_fetch(cpu, value): + prepare_for_fetch(cpu, (value & 0xFF00) >> 8, value & 0x00FF) + +def prepare_for_fetch(cpu, value, valueLo=None): + pc = cpu.pc.get() + if valueLo is not None: + cpu.rom[pc] = valueLo & 0xFF + cpu.memory.write(pc, valueLo & 0xFF) + pc += 1 + cpu.rom[pc] = value & 0xFF + cpu.memory.write(pc, value & 0xFF) + +def test_prepare_for_fetch(): + cpu = get_cpu() + value = 0x12 + prepare_for_fetch(cpu, value+1, value) + assert cpu.fetch() == value + assert cpu.fetch() == value+1 + +def prepare_for_pop(cpu, value, valueLo=None): + sp = cpu.sp.get() + if valueLo is not None: + cpu.memory.write(sp, valueLo & 0xFF) + sp += 1 + cpu.memory.write(sp, value & 0xFF) + +def test_prepare_for_pop(): + cpu = get_cpu() + value = 0x12 + prepare_for_pop(cpu, value+1, value) + assert cpu.pop() == value + assert cpu.pop() == value+1 + +def set_registers(registers, value): + #if registers is not list: + # registers = [registers] + for register in registers: + register.set(value); + + +def method_value_call(cpu, method, number): + method(cpu, NumberCallWrapper(number)) + +def method_register_call(cpu, method, register): + method(cpu, RegisterCallWrapper(register), RegisterCallWrapper(register)) + +def method_register_value_call(cpu, method, register, number): + method(cpu, RegisterCallWrapper(register), RegisterCallWrapper(register), + number) + +# Tests ----------------------------------------------------------------------- + + +def test_add_a_with_carry(): + cpu = get_cpu() + cpu.f.set(0xFF) + cpu.a.set(0x00) + method_value_call(cpu, CPU.add_a_with_carry, 0x00) + assert cpu.a.get() == 0x01 + assert_flags(cpu, z=False, n=False, h=False, c=False) + add_flag_test(cpu, CPU.add_a_with_carry) + +def add_flag_test(cpu, method): + cpu.f.set(0x00) + cpu.a.set(0x00) + method_value_call(cpu, CPU.add_a_with_carry, 0x00) + assert cpu.a.get() == 0x00 + assert_flags(cpu, z=True, n=False, h=False, c=False) + + cpu.f.set(0x00) + cpu.a.set(0x0F) + method_value_call(cpu, CPU.add_a_with_carry, 0x01) + assert cpu.a.get() == 0x10 + assert_flags(cpu, z=False, n=False, h=True, c=False) + + cpu.f.set(0x00) + cpu.a.set(0xFF) + method_value_call(cpu, CPU.add_a_with_carry, 0xF0) + assert cpu.a.get() == 0xEF + assert_flags(cpu, z=False, n=False, h=False, c=True) + + cpu.f.set(0x00) + cpu.a.set(0xFF) + method_value_call(cpu, CPU.add_a_with_carry, 0x01) + assert cpu.a.get() == 0x00 + assert_flags(cpu, z=True, n=False, h=True, c=True) + +def test_add_a(): + py.test.skip("Flag check broken") + cpu = get_cpu() + cpu.f.set(0xFF) + cpu.a.set(0x00) + method_value_call(cpu, CPU.add_a, 0x00) + assert cpu.a.get() == 0x00 + assert_flags(cpu, z=True, n=False, h=False, c=False) + add_flag_test(cpu, CPU.add_a) + + +def test_add_hl(): + py.test.skip("Carry flag check broken") + cpu = get_cpu() + cpu.f.set(0xFF) + cpu.hl.set(0x0000) + method_value_call(cpu, CPU.add_hl, 0x0000) + assert cpu.hl.get() == 0x0000 + assert_flags(cpu, z=True, n=False, h=False, c=False) + + cpu.f.set(0x00) + cpu.hl.set(0x0000) + method_value_call(cpu, CPU.add_hl, 0x0000) + assert cpu.hl.get() == 0x0000 + assert_flags(cpu, z=False, n=False, h=False, c=False) + + cpu.f.set(0x00) + cpu.hl.set(0x0000) + method_value_call(cpu, CPU.add_hl, 0x00) + assert cpu.hl.get() == 0x0000 + assert_flags(cpu, z=False, n=False, h=False, c=False) + + cpu.f.set(0x00) + cpu.hl.set(0x0F00) + method_value_call(cpu, CPU.add_hl, 0x0100) + assert cpu.hl.get() == 0x1000 + assert_flags(cpu, z=False, n=False, h=True, c=False) + + cpu.f.set(0x00) + cpu.hl.set(0xFF00) + method_value_call(cpu, CPU.add_hl, 0xF000) + assert cpu.hl.get() == 0xEF00 + assert_flags(cpu, z=False, n=False, h=False, c=True) + + cpu.f.set(0x00) + cpu.hl.set(0xFF00) + method_value_call(cpu, CPU.add_hl, 0x0100) + assert cpu.hl.get() == 0x0000 + assert_flags(cpu, z=False, n=False, h=True, c=True) + +def test_add_sp(): + py.test.skip("not yet implemented") + cpu = get_cpu() + +def test_and_a(): + cpu = get_cpu() + cpu.f.set(0xFF) + cpu.a.set(0xFF) + method_value_call(cpu, CPU.and_a, 0x00) + assert cpu.a.get() == 0x00 + assert_flags(cpu, z=True, n=False, h=True, c=False) + + cpu.a.set(0xFF) + method_value_call(cpu, CPU.and_a, 0x12) + assert cpu.a.get() == 0x12 + assert_flags(cpu, z=False, n=False, h=True, c=False) + + +def test_or_a(): + cpu = get_cpu() + cpu.f.set(0xFF) + cpu.a.set(0x00) + method_value_call(cpu, CPU.or_a, 0xFF) + assert cpu.a.get() == 0xFF + assert_flags(cpu, z=False, n=False, h=False, c=False) + + cpu.f.set(0x00) + cpu.a.set(0x00) + method_value_call(cpu, CPU.or_a, 0x00) + assert cpu.a.get() == 0x00 + assert_flags(cpu, z=True, n=False, h=False, c=False) + + cpu.f.set(0x00) + cpu.a.set(0xFF) + method_value_call(cpu, CPU.or_a, 0x00) + assert cpu.a.get() == 0xFF + assert_flags(cpu, z=False, n=False, h=False, c=False) + + cpu.f.set(0x00) + cpu.a.set(0x01) + method_value_call(cpu, CPU.or_a, 0x00) + assert cpu.a.get() == 0x01 + assert_flags(cpu, z=False, n=False, h=False, c=False) + + cpu.f.set(0x00) + cpu.a.set(0x01) + method_value_call(cpu, CPU.or_a, 0xFF) + assert cpu.a.get() == 0xFF + assert_flags(cpu, z=False, n=False, h=False, c=False) + + + +def test_xor_a(): + cpu = get_cpu() + cpu.f.set(0xFF) + cpu.a.set(0x00) + method_value_call(cpu, CPU.xor_a, 0xFF) + assert cpu.a.get() == 0xFF + assert_flags(cpu, z=False, n=False, h=False, c=False) + + cpu.f.set(0xFF) + cpu.a.set(0xFF) + method_value_call(cpu, CPU.xor_a, 0xFF) + assert cpu.a.get() == 0x00 + assert_flags(cpu, z=True, n=False, h=False, c=False) + + cpu.f.set(0x00) + cpu.a.set(0x01) + method_value_call(cpu, CPU.xor_a, 0x00) + assert cpu.a.get() == 0x01 + assert_flags(cpu, z=False, n=False, h=False, c=False) + + cpu.f.set(0x00) + cpu.a.set(0x01) + method_value_call(cpu, CPU.xor_a, 0xFF) + assert cpu.a.get() == 0xFF - 0x01 + assert_flags(cpu, z=False, n=False, h=False, c=False) + + cpu.f.set(0x00) + cpu.a.set(0x00) + method_value_call(cpu, CPU.xor_a, 0x00) + assert cpu.a.get() == 0x00 + assert_flags(cpu, z=True, n=False, h=False, c=False) + +def test_bit(): + cpu = get_cpu() + cpu.f.set(0xFF) + cpu.a.set(0xFF) + method_register_value_call(cpu, CPU.test_bit, cpu.a, 0x00) + assert cpu.a.get() == 0xFF + assert_flags(cpu, z=False, n=False, h=True, c=True) + + cpu.f.set(0x00) + cpu.a.set(0xFF) + method_register_value_call(cpu, CPU.test_bit, cpu.a, 0x00) + assert cpu.a.get() == 0xFF + assert_flags(cpu, z=False, n=False, h=True, c=False) + + cpu.f.set(0x00) + cpu.a.set(0x40) + method_register_value_call(cpu, CPU.test_bit, cpu.a, 0x05) + assert_flags(cpu, z=True, n=False, h=True, c=False) + + method_register_value_call(cpu, CPU.test_bit, cpu.a, 0x06) + assert cpu.a.get() == 0x40 + assert_flags(cpu, z=False, n=False, h=True, c=False) + + method_register_value_call(cpu, CPU.test_bit, cpu.a, 0x07) + assert_flags(cpu, z=True, n=False, h=True, c=False) + +def test_set_bit(): + cpu = get_cpu() + cpu.f.set(0xFF) + cpu.a.set(0x00) + method_register_value_call(cpu, CPU.set_bit, cpu.a, 0x00) + assert cpu.a.get() == 0x01 + assert cpu.f.get() == 0xFF + + for i in range(8): + cpu = get_cpu() + cpu.f.set(0x00) + cpu.a.set(0x00) + method_register_value_call(cpu, CPU.set_bit, cpu.a, i) + assert cpu.a.get() == 0x01 << i + assert cpu.f.get() == 0x00 + +def test_reset_bit(): + cpu = get_cpu() + cpu.f.set(0xFF) + cpu.a.set(0x01) + method_register_value_call(cpu, CPU.reset_bit, cpu.a, 0x00) + assert cpu.a.get() == 0x00 + assert cpu.f.get() == 0xFF + + for i in range(8): + cpu = get_cpu() + cpu.f.set(0x00) + cpu.a.set(0xFF) + method_register_value_call(cpu, CPU.reset_bit, cpu.a, i) + assert cpu.a.get() == 0xFF - (0x01 << i) + assert cpu.f.get() == 0x00 + + +def test_unconditional_call(): + cpu = get_cpu() + cpu.f.set(0x12) + cpu.pc.set(0x1234) + assert cpu.pc.get_hi() == 0x12 + assert cpu.pc.get_lo() == 0x34 + prepare_for_double_fetch(cpu, 0x5678) + cpu.unconditional_call() + assert cpu.f.get() == 0x12 + assert cpu.pop() == 0x34+2 + assert cpu.pop() == 0x12 + assert cpu.pc.get() == 0x5678 + + +def test_conditional_call(): + cpu = get_cpu() + cpu.f.set(0x12) + cpu.pc.set(0x1234) + cpu.conditional_call(False) + assert cpu.pc.get() == 0x1234+2 + assert cpu.f.get() == 0x12 + + cpu.reset() + cpu.f.set(0x12) + cpu.pc.set(0x1234) + assert cpu.pc.get_hi() == 0x12 + assert cpu.pc.get_lo() == 0x34 + prepare_for_double_fetch(cpu, 0x5678) + cpu.conditional_call(True) + assert cpu.f.get() == 0x12 + assert cpu.pop() == 0x34+2 + assert cpu.pop() == 0x12 + assert cpu.pc.get() == 0x5678 + +def test_complement_carry_flag(): + cpu = get_cpu() + cpu.f.set(0xFF) + cpu.complement_carry_flag() + assert_flags(cpu, z=True, n=False, h=False, c=False) + + cpu.complement_carry_flag() + assert_flags(cpu, z=True, n=False, h=False, c=True) + + cpu.f.set(0x00) + cpu.complement_carry_flag() + assert_flags(cpu, z=False, n=False, h=False, c=True) + +def test_compare_a(): + cpu = get_cpu() + cpu.f.set(0xFF) + cpu.a.set(0x00) + method_value_call(cpu, CPU.compare_a, 0x00) + assert_flags(cpu, z=True, n=True, h=False, c=False) + + cpu.f.set(0x00) + cpu.a.set(0x00) + method_value_call(cpu, CPU.compare_a, 0x00) + assert_flags(cpu, z=True, n=True, h=False, c=False) + + cpu.f.set(0x00) + cpu.a.set(0x11) + method_value_call(cpu, CPU.compare_a, 0x02) + assert_flags(cpu, z=False, n=True, h=True, c=False) + + cpu.f.set(0x00) + cpu.a.set(0x0F) + method_value_call(cpu, CPU.compare_a, 0xFF) + assert_flags(cpu, z=False, n=True, h=False, c=True) + + cpu.f.set(0x00) + cpu.a.set(0x00) + method_value_call(cpu, CPU.compare_a, 0x01) + assert_flags(cpu, z=False, n=True, h=True, c=True) + +def test_complement_a(): + cpu = get_cpu() + cpu.f.set(0xFF) + cpu.a.set(0xF0) + cpu.complement_a() + assert cpu.a.get() == 0x0F + assert_flags(cpu, z=True, n=True, h=True, c=True) + + cpu.f.set(0x00) + cpu.complement_a() + assert cpu.a.get() == 0xF0 + assert_flags(cpu, z=False, n=True, h=True, c=False) + +def test_decimal_adjust_a(): + py.test.skip("not yet implemented") + cpu = get_cpu() + cpu.f.set(0xFF) + cpu.decimal_adjust_a() + assert_flags(cpu, z=False, n=True, h=False, c=False) + + cpu.f.set(0x00) + cpu.decimal_adjust_a() + assert_flags(cpu, z=False, n=False, h=False, c=False) + +def test_decrement_register(): + cpu = get_cpu() + cpu.f.set(0xFF) + cpu.a.set(0xFF) + method_register_call(cpu, CPU.dec, cpu.a) + assert cpu.a.get() == 0xFE + assert_flags(cpu, z=False, n=True, h=False, c=True) + + cpu.f.set(0x00) + method_register_call(cpu, CPU.dec, cpu.a) + assert cpu.a.get() == 0xFD + assert_flags(cpu, z=False, n=True, h=False, c=False) + + cpu.f.set(0x00) + cpu.a.set(0x01) + method_register_call(cpu, CPU.dec, cpu.a) + assert cpu.a.get() == 0x00 + assert_flags(cpu, z=True, n=True, h=False, c=False) + + cpu.f.set(0x00) + cpu.a.set(0x10) + method_register_call(cpu, CPU.dec, cpu.a) + assert cpu.a.get() == 0x0F + assert_flags(cpu, z=False, n=True, h=True, c=False) + +def test_increment_register(): + cpu = get_cpu() + cpu.f.set(0xFF) + cpu.a.set(0xF1) + method_register_call(cpu, CPU.inc, cpu.a) + assert cpu.a.get() == 0xF2 + assert_flags(cpu, z=False, n=False, h=False, c=True) + + cpu.f.set(0x00) + method_register_call(cpu, CPU.inc, cpu.a) + assert cpu.a.get() == 0xF3 + assert_flags(cpu, z=False, n=False, h=False, c=False) + + cpu.f.set(0x00) + cpu.a.set(0x0F) + method_register_call(cpu, CPU.inc, cpu.a) + assert cpu.a.get() == 0x10 + assert_flags(cpu, z=False, n=False, h=True, c=False) + + cpu.f.set(0x00) + cpu.a.set(0xFF) + method_register_call(cpu, CPU.inc, cpu.a) + assert cpu.a.get() == 0x00 + assert_flags(cpu, z=True, n=False, h=True, c=False) + +def test_decrement_double_register(): + cpu = get_cpu() + cpu.f.set(0xFF) + cpu.bc.set(0xFFFF) + cpu.dec_double_register(cpu.bc) + assert cpu.bc.get() == 0xFFFE + assert cpu.f.get() == 0xFF + + cpu.f.set(0xFF) + cpu.dec_double_register(cpu.bc) + assert cpu.bc.get() == 0xFFFD + assert cpu.f.get() == 0xFF + + cpu.f.set(0xFF) + cpu.bc.set(0x0000) + cpu.dec_double_register(cpu.bc) + assert cpu.bc.get() == 0xFFFF + assert cpu.f.get() == 0xFF + +def test_increment_double_register(): + cpu = get_cpu() + cpu.f.set(0xFF) + cpu.bc.set(0xFFFD) + cpu.inc_double_register(cpu.bc) + assert cpu.bc.get() == 0xFFFE + assert cpu.f.get() == 0xFF + + cpu.f.set(0xFF) + cpu.inc_double_register(cpu.bc) + assert cpu.bc.get() == 0xFFFF + assert cpu.f.get() == 0xFF + + cpu.f.set(0xFF) + cpu.inc_double_register(cpu.bc) + assert cpu.bc.get() == 0x0000 + assert cpu.f.get() == 0xFF + +def test_disable_interrupts(): + cpu = get_cpu() + cpu.f.set(0xFF) + cpu.disable_interrups() + assert cpu.f.get() == 0xFF + + cpu.f.set(0x00) + cpu.disable_interrups() + assert cpu.f.get() == 0x00 + +def test_enable_interrupts(): + cpu = get_cpu() + cpu.f.set(0xFF) + cpu.enable_interrupts() + assert cpu.f.get() == 0xFF + + cpu.f.set(0x00) + cpu.enable_interrupts() + assert cpu.f.get() == 0x00 + +def test_jump(): + cpu = get_cpu() + cpu.f.set(0xFF) + prepare_for_double_fetch(cpu, 0x1234) + cpu.jump() + assert cpu.f.get() == 0xFF + assert cpu.pc.get() == 0x1234 + +def test_conditional_jump(): + cpu = get_cpu() + cpu.f.set(0xFF) + prepare_for_double_fetch(cpu, 0x1234) + cpu.conditional_jump(True) + assert cpu.f.get() == 0xFF + assert cpu.pc.get() == 0x1234 + + cpu.pc.set(0x1234) + prepare_for_double_fetch(cpu, 0x1234) + cpu.conditional_jump(False) + assert cpu.f.get() == 0xFF + assert cpu.pc.get() == 0x1234+2 + +def test_process_2_complement(): + cpu = get_cpu() + + assert cpu.process_2_complement(0x00) == 0 + assert cpu.process_2_complement(0xFF) == -1 + + for i in range(0x7E): + assert cpu.process_2_complement(i) == i + + for i in range(1, 0x7E): + assert cpu.process_2_complement(0xFF - i+1) == -i + +def test_relative_jump(): + cpu = get_cpu() + cpu.f.set(0xFF) + for i in range(0x7F): + cpu.pc.set(0x1234) + prepare_for_fetch(cpu, i) + cpu.relative_jump() + assert cpu.f.get() == 0xFF + #+1 fpr a single fetch + assert cpu.pc.get() == 0x1234+1 + i + + for i in range(1, 0x7F): + cpu.pc.set(0x1234) + prepare_for_fetch(cpu, 0xFF - i+1) + cpu.relative_jump() + assert cpu.f.get() == 0xFF + #+1 fpr a single fetch + assert cpu.pc.get() == 0x1234+1 - i + +def test_conditional_relative_jump(): + cpu = get_cpu() + cpu.f.set(0xFF) + for i in range(0x7F): + cpu.pc.set(0x1234) + prepare_for_fetch(cpu, i) + cpu.relative_conditional_jump(True) + assert cpu.f.get() == 0xFF + #+1 fpr a single fetch + assert cpu.pc.get() == 0x1234+1 + i + + cpu.pc.set(0x1234) + prepare_for_fetch(cpu, 0x12) + cpu.relative_conditional_jump(False) + assert cpu.f.get() == 0xFF + assert cpu.pc.get() == 0x1234+1 + +def store_fetch_added_sp_in_hl(): + cpu = get_cpu() + cpu.f.set(0xFF) + cpu.sp.set(0x1234) + prepare_for_fetch(0x02) + cpu.store_fetch_added_sp_in_hl() + assert cpu.hl.get() == 0x1234 + 0x02 + assert_flags(cpu, z=False, n=False, h=False, c=False) + + + cpu.f.set(0x00) + cpu.sp.set(0x1234) + prepare_for_fetch(0x02) + cpu.store_fetch_added_sp_in_hl() + assert cpu.hl.get() == 0x1234 + 0x02 + assert_flags(cpu, z=False, n=False, h=False, c=False) + + + cpu.f.set(0xFF) + cpu.sp.set(0x1234) + prepare_for_fetch(0xFF) + cpu.store_fetch_added_sp_in_hl() + assert cpu.hl.get() == 0x1234 - 1 + assert_flags(cpu, z=False, n=False, h=False, c=False) + +def test_rotate_left(): + cpu = get_cpu() + cpu.f.set(0x00) + cpu.a.set(0xFF) + method_register_call(cpu, CPU.rotate_left, cpu.a) + assert cpu.a.get() == 0xFE + assert_flags(cpu, z=False, n=False, h=False, c=True) + + cpu = get_cpu() + cpu.f.set(0xFF) + cpu.a.set(0xFF) + method_register_call(cpu, CPU.rotate_left, cpu.a) + assert cpu.a.get() == 0xFE+1 + assert_flags(cpu, z=False, n=False, h=False, c=True) + + cpu.f.set(0x00) + cpu.a.set(0x01) + method_register_call(cpu, CPU.rotate_left, cpu.a) + assert cpu.a.get() == 0x02 + assert_flags(cpu, z=False, n=False, h=False, c=False) + + cpu.f.set(0x00) + cpu.a.set(0x80) + method_register_call(cpu, CPU.rotate_left, cpu.a) + assert cpu.a.get() == 0x00 + assert_flags(cpu, z=True, n=False, h=False, c=True) + + cpu.f.set(0xFF) + cpu.a.set(0x80) + method_register_call(cpu, CPU.rotate_left, cpu.a) + assert cpu.a.get() == 0x01 + assert_flags(cpu, z=False, n=False, h=False, c=True) + + cpu.f.set(0x00) + cpu.a.set(0x40) + method_register_call(cpu, CPU.rotate_left, cpu.a) + assert cpu.a.get() == 0x80 + assert_flags(cpu, z=False, n=False, h=False, c=False) + + cpu.f.set(0x00) + cpu.a.set(0x7F) + method_register_call(cpu, CPU.rotate_left, cpu.a) + assert cpu.a.get() == 0xFE + assert_flags(cpu, z=False, n=False, h=False, c=False) + +def test_rotate_right(): + cpu = get_cpu() + cpu.f.set(0x00) + cpu.a.set(0xFF) + method_register_call(cpu, CPU.rotate_right, cpu.a) + assert cpu.a.get() == 0x7F + assert_flags(cpu, z=False, n=False, h=False, c=True) + + cpu = get_cpu() + cpu.f.set(0xFF) + cpu.a.set(0xFF) + method_register_call(cpu, CPU.rotate_right, cpu.a) + assert cpu.a.get() == 0x7F + 0x80 + assert_flags(cpu, z=False, n=False, h=False, c=True) + + cpu.f.set(0x00) + cpu.a.set(0x01) + method_register_call(cpu, CPU.rotate_right, cpu.a) + assert cpu.a.get() == 0x00 + assert_flags(cpu, z=True, n=False, h=False, c=True) + + cpu.f.set(0xFF) + cpu.a.set(0x01) + method_register_call(cpu, CPU.rotate_right, cpu.a) + assert cpu.a.get() == 0x80 + assert_flags(cpu, z=False, n=False, h=False, c=True) + + cpu.f.set(0x00) + cpu.a.set(0x08) + method_register_call(cpu, CPU.rotate_right, cpu.a) + assert cpu.a.get() == 0x04 + assert_flags(cpu, z=False, n=False, h=False, c=False) + + for i in range(0, 7): + cpu.f.set(0x00) + cpu.a.set(0x80 >> i) + method_register_call(cpu, CPU.rotate_right, cpu.a) + assert cpu.a.get() == 0x80 >> (i+1) + assert_flags(cpu, z=False, n=False, h=False, c=False) + +def test_rotate_left_circular(): + cpu = get_cpu() + cpu.f.set(0xFF) + cpu.a.set(0xFF) + method_register_call(cpu, CPU.rotate_left_circular, cpu.a) + assert cpu.a.get() == 0xFF + assert_flags(cpu, z=False, n=False, h=False, c=True) + + cpu = get_cpu() + cpu.f.set(0x00) + cpu.a.set(0xFF) + method_register_call(cpu, CPU.rotate_left_circular, cpu.a) + assert cpu.a.get() == 0xFF + assert_flags(cpu, z=False, n=False, h=False, c=True) + + cpu.f.set(0x00) + cpu.a.set(0x80) + method_register_call(cpu, CPU.rotate_left_circular, cpu.a) + assert cpu.a.get() == 0x01 + assert_flags(cpu, z=False, n=False, h=False, c=True) + + cpu.f.set(0xFF) + cpu.a.set(0x01) + method_register_call(cpu, CPU.rotate_left_circular, cpu.a) + assert cpu.a.get() == 0x02 + assert_flags(cpu, z=False, n=False, h=False, c=False) + +def test_rotate_right_circular(): + cpu = get_cpu() + cpu.f.set(0xFF) + cpu.a.set(0xFF) + method_register_call(cpu, CPU.rotate_right_circular, cpu.a) + assert cpu.a.get() == 0xFF + assert_flags(cpu, z=False, n=False, h=False, c=True) + + cpu = get_cpu() + cpu.f.set(0x00) + cpu.a.set(0xFF) + method_register_call(cpu, CPU.rotate_right_circular, cpu.a) + assert cpu.a.get() == 0xFF + assert_flags(cpu, z=False, n=False, h=False, c=True) + + cpu.f.set(0x00) + cpu.a.set(0x01) + method_register_call(cpu, CPU.rotate_right_circular, cpu.a) + assert cpu.a.get() == 0x80 + assert_flags(cpu, z=False, n=False, h=False, c=True) + + cpu.f.set(0xFF) + cpu.a.set(0x02) + method_register_call(cpu, CPU.rotate_right_circular, cpu.a) + assert cpu.a.get() == 0x01 + assert_flags(cpu, z=False, n=False, h=False, c=False) + + +def test_subtract_with_carry_a(): + cpu = get_cpu() + cpu.f.set(0xFF) + cpu.a.set(0x01) + method_value_call(cpu, CPU.subtract_with_carry_a, 0x00) + assert cpu.a.get() == 0x00 + assert_flags(cpu, z=True, n=True, h=False, c=False) + + cpu.f.set(0x00) + cpu.a.set(0x01) + method_value_call(cpu, CPU.subtract_with_carry_a, 0x00) + assert cpu.a.get() == 0x01 + assert_flags(cpu, z=False, n=True, h=False, c=False) + + cpu.f.set(0x00) + cpu.a.set(0x10) + method_value_call(cpu, CPU.subtract_with_carry_a, 0x01) + assert cpu.a.get() == 0x0F + assert_flags(cpu, z=False, n=True, h=True, c=False) + + cpu.f.set(0x00) + cpu.a.set(0x00) + method_value_call(cpu, CPU.subtract_with_carry_a, 0x01) + assert cpu.a.get() == 0xFF + assert_flags(cpu, z=False, n=True, h=True, c=True) + + # FIXME add separated Test for each flag + + +def test_swap(): + cpu = get_cpu() + cpu.f.set(0xFF) + cpu.a.set(0x12) + method_register_call(cpu, CPU.swap, cpu.a) + assert cpu.a.get() == 0x21 + assert_flags(cpu, z=False, n=False, h=False, c=False) + + cpu.f.set(0xFF) + cpu.a.set(0x00) + method_register_call(cpu, CPU.swap, cpu.a) + assert cpu.a.get() == 0x00 + assert_flags(cpu, z=True, n=False, h=False, c=False) + + cpu.f.set(0x00) + cpu.a.set(0x34) + method_register_call(cpu, CPU.swap, cpu.a) + assert cpu.a.get() == 0x43 + assert_flags(cpu, z=False, n=False, h=False, c=False) + + \ No newline at end of file Modified: pypy/dist/pypy/lang/gameboy/test/test_joypad.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/test/test_joypad.py (original) +++ pypy/dist/pypy/lang/gameboy/test/test_joypad.py Sat May 31 09:52:43 2008 @@ -44,11 +44,11 @@ # TEST BUTTON ------------------------------------------------------------------ def test_ini(): - value = 0xf + value = 0xf button = Button(value) assert button.opposite_button is None - assert button.code_value == value - assert button.is_pressed() == False + assert button.code_value == value + assert button.is_pressed() == False button2 = Button(value, button) assert button2.opposite_button == button @@ -67,74 +67,74 @@ button2.press() assert button2.is_pressed() == True button.press() - assert button.is_pressed() == True + assert button.is_pressed() == True assert button2.is_pressed() == False button.release() - assert button.is_pressed() == False + assert button.is_pressed() == False assert button2.is_pressed() == False # TEST JOYPAD DRIVER ----------------------------------------------------------- def test_ini(): driver = get_driver() - assert driver.raised == False - assert driver.get_button_code() == 0 + assert driver.raised == False + assert driver.get_button_code() == 0 assert driver.get_direction_code() == 0 def test_isRaised(): - driver = get_driver() + driver = get_driver() driver.raised = True - assert driver.raised == True + assert driver.raised == True assert driver.is_raised() == True - assert driver.raised == False + assert driver.raised == False def test_button_code_values(): driver = get_driver() - assert driver.up.code_value == constants.BUTTON_UP - assert driver.right.code_value == constants.BUTTON_RIGHT - assert driver.down.code_value == constants.BUTTON_DOWN - assert driver.left.code_value == constants.BUTTON_LEFT + assert driver.up.code_value == constants.BUTTON_UP + assert driver.right.code_value == constants.BUTTON_RIGHT + assert driver.down.code_value == constants.BUTTON_DOWN + assert driver.left.code_value == constants.BUTTON_LEFT assert driver.select.code_value == constants.BUTTON_SELECT - assert driver.start.code_value == constants.BUTTON_START - assert driver.a.code_value == constants.BUTTON_A - assert driver.b.code_value == constants.BUTTON_B + assert driver.start.code_value == constants.BUTTON_START + assert driver.a.code_value == constants.BUTTON_A + assert driver.b.code_value == constants.BUTTON_B def test_toggle_opposite_directions(): driver = get_driver() - directions = [(driver.button_up, driver.up, driver.down), - (driver.button_down, driver.down, driver.up), - (driver.button_left, driver.left, driver.right), - (driver.button_right, driver.right, driver.left)] + directions = [(driver.button_up, driver.up, driver.down), + (driver.button_down, driver.down, driver.up), + (driver.button_left, driver.left, driver.right), + (driver.button_right, driver.right, driver.left)] for dir in directions: - toggleFunction = dir[0] - button = dir[1] + toggleFunction = dir[0] + button = dir[1] opposite_button = dir[2] driver.reset() opposite_button.press() - assert driver.raised == False - assert button.is_pressed() == False + assert driver.raised == False + assert button.is_pressed() == False assert opposite_button.is_pressed() == True - assert driver.get_direction_code() == opposite_button.code_value - assert driver.get_button_code() == 0 + assert driver.get_direction_code() == opposite_button.code_value + assert driver.get_button_code() == 0 toggleFunction() - assert driver.raised == True - assert button.is_pressed() == True + assert driver.raised == True + assert button.is_pressed() == True assert opposite_button.is_pressed() == False - assert driver.get_direction_code() == button.code_value - assert driver.get_button_code() == 0 + assert driver.get_direction_code() == button.code_value + assert driver.get_button_code() == 0 toggleFunction(False) - assert button.is_pressed() == False + assert button.is_pressed() == False assert opposite_button.is_pressed() == False - assert driver.get_direction_code() == 0 - assert driver.get_button_code() == 0 + assert driver.get_direction_code() == 0 + assert driver.get_button_code() == 0 def test_toggle_buttons(): - driver = get_driver() + driver = get_driver() buttons = [(driver.button_select, driver.select), (driver.button_start, driver.start), (driver.button_a, driver.a), @@ -144,24 +144,24 @@ button = button[1] driver.reset() - assert button.is_pressed() == False - assert driver.get_button_code() == 0 + assert button.is_pressed() == False + assert driver.get_button_code() == 0 assert driver.get_direction_code() == 0 toggleFunction() - assert driver.raised == True - assert button.is_pressed() == True - assert driver.get_button_code() == button.code_value + assert driver.raised == True + assert button.is_pressed() == True + assert driver.get_button_code() == button.code_value assert driver.get_direction_code() == 0 toggleFunction(False) - assert button.is_pressed() == False - assert driver.get_button_code() == 0 + assert button.is_pressed() == False + assert driver.get_button_code() == 0 assert driver.get_direction_code() == 0 def test_toggle_multiple_buttons(): - driver = get_driver() + driver = get_driver() buttons = [(driver.button_select, driver.select), (driver.button_start, driver.start), (driver.button_a, driver.a), @@ -205,15 +205,15 @@ def test_emulate(): joypad = get_joypad() - ticks = 2 + ticks = 2 cycles = joypad.cycles joypad.emulate(ticks) assert cycles - joypad.cycles == ticks def test_emulate_zero_ticks(): - joypad = get_joypad() + joypad = get_joypad() joypad.cycles = 2 - ticks = 2 + ticks = 2 joypad.emulate(ticks) assert joypad.cycles == constants.JOYPAD_CLOCK @@ -226,15 +226,15 @@ joypad.cycles = 2 ticks = 2 joypad.emulate(ticks) - assert joypad.cycles == constants.JOYPAD_CLOCK - assert joypad.joyp == value + assert joypad.cycles == constants.JOYPAD_CLOCK + assert joypad.joyp == value assert joypad.button_code == 0 def test_read_write(): joypad = get_joypad() - value = 0x2 + value = 0x2 joypad.write(constants.JOYP, value) - joyp = 0xC + (value & 0x3) + joyp = 0xC + (value & 0x3) assert joypad.joyp == joyp joyp = (joyp << 4) + 0xF assert joypad.read(constants.JOYP) == joyp From cami at codespeak.net Sat May 31 10:25:04 2008 From: cami at codespeak.net (cami at codespeak.net) Date: Sat, 31 May 2008 10:25:04 +0200 (CEST) Subject: [pypy-svn] r55441 - in pypy/dist/pypy/lang/gameboy: . test Message-ID: <20080531082504.E95D3398001@codespeak.net> Author: cami Date: Sat May 31 10:25:01 2008 New Revision: 55441 Modified: pypy/dist/pypy/lang/gameboy/cpu.py pypy/dist/pypy/lang/gameboy/test/test_cpu.py pypy/dist/pypy/lang/gameboy/test/test_cpu_2.py Log: removed some clashing tests from test_cpu.py. test for cycles are now in test_cpu.py, those for flags in test_cpu_2.py Modified: pypy/dist/pypy/lang/gameboy/cpu.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/cpu.py (original) +++ pypy/dist/pypy/lang/gameboy/cpu.py Sat May 31 10:25:01 2008 @@ -479,39 +479,38 @@ self.ld(CPUFetchCaller(self), setCaller) def add_a(self, getCaller, setCaller=None): + data = getCaller.get() # ALU, 1 cycle - added = (self.a.get() + getCaller.get()) & 0xFF - self.f.z_flag_compare(added) - self.f.h_flag_compare(added, self.a.get(), inverted=True) - self.f.c_flag = (added < self.a.get()) - self.a.set(added) # 1 cycle + added = (self.a.get() + data) & 0xFF + self.add_sub_flag_finish(added, data) def add_hl(self, register): # 2 cycles - a=1 - added = (self.hl.get() + register.get()) & 0xFFFF # 1 cycle + data = register.get() + added = (self.hl.get() + data) # 1 cycle self.f.partial_reset(keep_z=True) - self.f.h_flag_compare((added >> 8), self.hl.get()) - self.f.c_flag_compare(added, self.hl.get()) - self.hl.set(added) + if ((added ^ self.hl.get() ^ data) & 0x1000) != 0: + self.f.h_flag = True + self.f.c_flag = (added >= 0x10000 or added < 0) + self.hl.set(added & 0xFFFF) self.cycles -= 1 def add_a_with_carry(self, getCaller, setCaller=None): # 1 cycle data = getCaller.get() s = self.a.get() + data + int(self.f.c_flag) - self.carry_flag_finish(s,data) + self.add_sub_flag_finish(s,data) def subtract_with_carry_a(self, getCaller, setCaller=None): # 1 cycle data = getCaller.get() s = self.a.get() - data - int(self.f.c_flag) - self.carry_flag_finish(s, data) + self.add_sub_flag_finish(s, data) self.f.n_flag = True - def carry_flag_finish(self, s, data): + def add_sub_flag_finish(self, s, data): self.f.reset() - # set the hflag if the 0x10 bit was affected + # set the h flag if the 0x10 bit was affected if ((s ^ self.a.get() ^ data) & 0x10) != 0: self.f.h_flag = True self.f.c_flag = (s >= 0x100 or s < 0) Modified: pypy/dist/pypy/lang/gameboy/test/test_cpu.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/test/test_cpu.py (original) +++ pypy/dist/pypy/lang/gameboy/test/test_cpu.py Sat May 31 10:25:01 2008 @@ -636,14 +636,12 @@ cpu.a.set(value) cycle_test(cpu, 0x07, 1) assert_default_registers(cpu, a=((value << 1) | (value >> 7)) & 0xFF, f=None); - assert_default_flags(cpu, z_flag=False, c_flag=False) cpu.reset() value = 0x40 cpu.a.set(value) cycle_test(cpu, 0x07, 1) assert_default_registers(cpu, a=((value << 1) | (value >> 7)) & 0xFF, f=None); - assert_default_flags(cpu, z_flag=False, c_flag=True) # rrca def test_0x0F(): @@ -652,66 +650,44 @@ cpu.a.set(value) cycle_test(cpu, 0x0F, 1) assert_default_registers(cpu, a=((value >> 1) | (value << 7)) & 0xFF, f=None); - assert_default_flags(cpu, z_flag=False, c_flag=False) cpu.reset() value = 0x02 cpu.a.set(value) cycle_test(cpu, 0x0F, 1) assert_default_registers(cpu, a=((value >> 1) | (value << 7)) & 0xFF, f=None); - assert_default_flags(cpu, z_flag=False, c_flag=True) # rla def test_0x17(): cpu = get_cpu() value = 0x01 + cpu.f.set(0x00) cpu.a.set(value) - cpu.f.c_flag = False cycle_test(cpu, 0x17, 1) assert_default_registers(cpu, a=(value << 1) & 0xFF, f=None); - assert_default_flags(cpu, z_flag=False, c_flag=False) - - cpu.reset() - value = 0x01 - cpu.a.set(value) - cpu.f.c_flag = True - cycle_test(cpu, 0x17, 1) - assert_default_registers(cpu, a=((value << 1)+1) & 0xFF, f=None); - assert_default_flags(cpu, z_flag=False, c_flag=False) - - cpu.reset() - value = 0x40 - cpu.a.set(value) - cpu.f.c_flag = False - cycle_test(cpu, 0x17, 1) - assert_default_registers(cpu, a=(value << 1) & 0xFF, f=None); - assert_default_flags(cpu, z_flag=False, c_flag=True) # rra def test_0x1F(): cpu = get_cpu() value = 0x40 + cpu.f.set(0x00) cpu.a.set(value) - cpu.f.c_flag = False cycle_test(cpu, 0x1F, 1) assert_default_registers(cpu, a=(value >> 1) & 0xFF, f=None); - assert_default_flags(cpu, z_flag=False, c_flag=False) cpu.reset() + cpu.f.set(0x00) value = 0x40 cpu.a.set(value) - cpu.f.c_flag = True cycle_test(cpu, 0x1F, 1) - assert_default_registers(cpu, a=(0x08+(value >> 1)) & 0xFF, f=None); - assert_default_flags(cpu, z_flag=False, c_flag=False) + assert_default_registers(cpu, a=(value >> 1) & 0xFF, f=None); cpu.reset() + cpu.f.set(0x00) value = 0x02 cpu.a.set(value) - cpu.f.c_flag = False cycle_test(cpu, 0x1F, 1) assert_default_registers(cpu, a=(value >> 1) & 0xFF, f=None); - assert_default_flags(cpu, z_flag=False, c_flag=True) # daa def test_0x27(): @@ -728,7 +704,6 @@ cpu.a.set(value) cycle_test(cpu, 0x2F, 1) assert_default_registers(cpu, a=value^0xFF, f=None) - assert_default_flags(cpu, n_flag=True, h_flag=True) # scf def test_0x37(): @@ -788,21 +763,6 @@ assert store.get() == value opCode += 0x01 - -def test_add_flags(): - cpu = get_cpu() - - cpu.a.set(0) - cpu.b.set(0) - cpu.add_a(RegisterCallWrapper(cpu.b), None) - assert_default_flags(cpu, z_flag=True, h_flag=False) - - cpu.reset() - cpu.a.set(0x0F) - cpu.b.set(0x01) - cpu.add_a(RegisterCallWrapper(cpu.b), None) - assert_default_flags(cpu, z_flag=False, h_flag=True) - # add_A_B to add_A_A def test_0x80_to_0x87(): @@ -826,42 +786,6 @@ value += 3 opCode += 0x01 - -def test_adc_flags(): - cpu = get_cpu() - b = cpu.b - a = cpu.a - - cpu.reset() - a.set(0) - b.set(0) - cpu.add_with_carry(RegisterCallWrapper(cpu.b), None) - assert_default_registers(cpu, a=0, f=None) - assert_default_flags(cpu, z_flag=True, c_flag=False, h_flag=False) - - cpu.reset() - a.set(0) - b.set(0) - cpu.f.c_flag = True - cpu.add_with_carry(RegisterCallWrapper(cpu.b), None) - assert_default_registers(cpu, a=1, f=None) - assert_default_flags(cpu, z_flag=False, c_flag=False, h_flag=False) - - cpu.reset() - a.set(0xF0) - b.set(0xFF) - cpu.add_with_carry(RegisterCallWrapper(cpu.b), None) - # overflow for a - assert_default_registers(cpu, a=0xEF, bc=None, f=None) - assert_default_flags(cpu, z_flag=False, c_flag=True, h_flag=False) - - cpu.reset() - a.set(0x0F) - b.set(0x01) - cpu.add_with_carry(RegisterCallWrapper(cpu.b), None) - assert_default_registers(cpu, a=0x10, f=None, bc=None) - assert_default_flags(cpu, z_flag=False, c_flag=False, h_flag=True) - # adc_A_B to adx_A_A def test_0x88_to_0x8F(): cpu = get_cpu() @@ -911,36 +835,6 @@ assert cpu.a.get() == 0 value += 3 opCode += 0x01 - -def test_sbc_flags(): - cpu = get_cpu() - b = cpu.b - a = cpu.a - value = 0xFF - - cpu.reset() - a.set(value) - b.set(value) - cpu.subtract_with_carry(RegisterCallWrapper(cpu.b), None) - assert_default_registers(cpu, a=0, bc=None, f=None) - assert_default_flags(cpu, z_flag=True, c_flag=False, h_flag=False, n_flag=True) - - cpu.reset() - a.set(value) - b.set(value-1) - cpu.f.c_flag = True - cpu.subtract_with_carry(RegisterCallWrapper(cpu.b), None) - assert_default_registers(cpu, a=0, bc=None, f=None) - assert_default_flags(cpu, z_flag=True, c_flag=False, h_flag=False, n_flag=True) - - cpu.reset() - a.set(0x20) - b.set(0x01) - cpu.subtract_with_carry(RegisterCallWrapper(cpu.b), None) - # overflow for a - assert_default_registers(cpu, a=0x1F, bc=None, f=None) - assert_default_flags(cpu, z_flag=False, c_flag=False, h_flag=True, n_flag=True) - # sbc_A_B to sbc_A_A def test_0x98_0x9F(): @@ -973,20 +867,6 @@ value += 3 opCode += 0x01 - -def test_and_flags(): - cpu = get_cpu() - value = 0x12 - cpu.a.set(value) - cpu.b.set(value) - cpu.AND(RegisterCallWrapper(cpu.b), None) - assert_default_flags(cpu, z_flag=False) - - cpu.reset() - cpu.a.set(value) - cpu.b.set(0) - cpu.AND(RegisterCallWrapper(cpu.b), None) - assert_default_flags(cpu, z_flag=True) # and_A_B to and_A_A def test_0xA0_to_0xA7(): @@ -1007,27 +887,8 @@ assert cpu.a.get() == (value & value) else: assert cpu.a.get() == (valueA & value) - if cpu.a.get() == 0: - assert cpu.f.get() == constants.Z_FLAG - else: - assert cpu.f.get() == 0 value += 1 opCode += 0x01 - - -def test_xor_flags(): - cpu = get_cpu() - value = 0x12 - cpu.a.set(value) - cpu.b.set(value) - cpu.XOR(RegisterCallWrapper(cpu.b), None) - assert_default_flags(cpu, z_flag=True) - - cpu.reset() - cpu.a.set(value) - cpu.b.set(value+1) - cpu.XOR(RegisterCallWrapper(cpu.b), None) - assert_default_flags(cpu, z_flag=False) # xor_A_B to xor_A_A def test_0xA8_to_0xAF(): @@ -1048,26 +909,9 @@ assert cpu.a.get() == (value ^ value) else: assert cpu.a.get() == (valueA ^ value) - if cpu.a.get() == 0: - assert cpu.f.z_flag == True - else: - assert cpu.f.get() == 0 value += 1 opCode += 0x01 -def test_or_flags(): - cpu = get_cpu() - value = 0x12 - cpu.a.set(value) - cpu.b.set(value) - cpu.OR(RegisterCallWrapper(cpu.b), None) - assert_default_flags(cpu, z_flag=False) - - cpu.reset() - cpu.a.set(0) - cpu.b.set(0) - cpu.OR(RegisterCallWrapper(cpu.b), None) - assert_default_flags(cpu, z_flag=True) # or_A_B to or_A_A def test_0xB0_to_0xB7(): @@ -1088,34 +932,9 @@ assert cpu.a.get() == (value | value) else: assert cpu.a.get() == (valueA | value) - if cpu.a.get() == 0: - assert cpu.f.get() == constants.Z_FLAG - else: - assert cpu.f.get() == 0 value += 1 opCode += 0x01 -def test_cp_flags(): - cpu = get_cpu() - value = 0x12 - cpu.a.set(value) - cpu.b.set(value) - cpu.compare_a(RegisterCallWrapper(cpu.b), None) - assert_default_flags(cpu, z_flag=True, n_flag=True) - - cpu.reset() - cpu.a.set(value) - cpu.b.set(0) - cpu.compare_a(RegisterCallWrapper(cpu.b), None) - assert_default_flags(cpu, z_flag=False, n_flag=True) - - cpu.reset() - cpu.a.set(0xF0) - cpu.b.set(0x01) - cpu.compare_a(RegisterCallWrapper(cpu.b), None) - assert_default_flags(cpu, z_flag=False, h_flag=True, n_flag=True) - - # cp_A_B to cp_A_A def test_0xB8_to_0xBF_compare_a(): cpu = get_cpu() @@ -1133,13 +952,6 @@ cycle_test(cpu, opCode, numCycles) if register == cpu.a: valueA = value - assert cpu.f.n_flag == True - if valueA == value: - assert cpu.f.z_flag == True - if value < 0: - assert cpu.f.c_flag == True - if ((valueA-value) & 0x0F) > (valueA & 0x0F): - assert cpu.f.h_flag == True value += 1 opCode += 0x01 @@ -1554,21 +1366,6 @@ assert_default_registers(cpu, pc=pc+1) -def test_rotateLeft_flags(): - cpu = get_cpu() - a = cpu.a - a.set(0x01) - assert_default_flags(cpu) - cpu.rotate_left_a() - assert_default_flags(cpu, z_flag=False, c_flag=False) - assert_default_registers(cpu, a=0x02, f=None) - - cpu.reset() - a.set(0x40) - cpu.rotate_left_a() - assert_default_flags(cpu, z_flag=False, c_flag=True) - assert_default_registers(cpu, a=0x80, f=None) - # SECOND ORDER OPCODES --------------------------------------------------------- Modified: pypy/dist/pypy/lang/gameboy/test/test_cpu_2.py ============================================================================== --- pypy/dist/pypy/lang/gameboy/test/test_cpu_2.py (original) +++ pypy/dist/pypy/lang/gameboy/test/test_cpu_2.py Sat May 31 10:25:01 2008 @@ -158,7 +158,6 @@ assert_flags(cpu, z=True, n=False, h=True, c=True) def test_add_a(): - py.test.skip("Flag check broken") cpu = get_cpu() cpu.f.set(0xFF) cpu.a.set(0x00) @@ -169,7 +168,6 @@ def test_add_hl(): - py.test.skip("Carry flag check broken") cpu = get_cpu() cpu.f.set(0xFF) cpu.hl.set(0x0000) @@ -223,8 +221,7 @@ method_value_call(cpu, CPU.and_a, 0x12) assert cpu.a.get() == 0x12 assert_flags(cpu, z=False, n=False, h=True, c=False) - - + def test_or_a(): cpu = get_cpu() cpu.f.set(0xFF) @@ -257,8 +254,6 @@ assert cpu.a.get() == 0xFF assert_flags(cpu, z=False, n=False, h=False, c=False) - - def test_xor_a(): cpu = get_cpu() cpu.f.set(0xFF) @@ -348,8 +343,7 @@ method_register_value_call(cpu, CPU.reset_bit, cpu.a, i) assert cpu.a.get() == 0xFF - (0x01 << i) assert cpu.f.get() == 0x00 - - + def test_unconditional_call(): cpu = get_cpu() cpu.f.set(0x12) @@ -363,7 +357,6 @@ assert cpu.pop() == 0x12 assert cpu.pc.get() == 0x5678 - def test_conditional_call(): cpu = get_cpu() cpu.f.set(0x12) From arigo at codespeak.net Sat May 31 11:00:32 2008 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 31 May 2008 11:00:32 +0200 (CEST) Subject: [pypy-svn] r55442 - in pypy/dist/pypy/objspace: . std std/test Message-ID: <20080531090032.D0FCA168537@codespeak.net> Author: arigo Date: Sat May 31 11:00:30 2008 New Revision: 55442 Modified: pypy/dist/pypy/objspace/descroperation.py pypy/dist/pypy/objspace/std/test/test_unicodeobject.py pypy/dist/pypy/objspace/std/unicodeobject.py Log: A minimal change that fixes the bug compatibility issue with "unicode + string subclass". The change is similar to the Jython fix (mostly by accident, the extra check is smaller than in Jython). Modified: pypy/dist/pypy/objspace/descroperation.py ============================================================================== --- pypy/dist/pypy/objspace/descroperation.py (original) +++ pypy/dist/pypy/objspace/descroperation.py Sat May 31 11:00:30 2008 @@ -460,10 +460,20 @@ # __xxx__ and __rxxx__ methods where found by identity. # Note that space.is_w() is potentially not happy if one of them # is None (e.g. with the thunk space)... - if (w_left_src is not w_right_src # XXX - and space.is_true(space.issubtype(w_typ2, w_typ1))): - w_obj1, w_obj2 = w_obj2, w_obj1 - w_left_impl, w_right_impl = w_right_impl, w_left_impl + if w_left_src is not w_right_src: # XXX + # -- cpython bug compatibility: see objspace/std/test/ + # -- test_unicodeobject.test_str_unicode_concat_overrides. + # -- The following handles "unicode + string subclass" by + # -- pretending that the unicode is a superclass of the + # -- string, thus giving priority to the string subclass' + # -- __radd__() method. The case "string + unicode subclass" + # -- is handled directly by add__String_Unicode(). + if symbol == '+' and space.is_w(w_typ1, space.w_unicode): + w_typ1 = space.w_basestring + # -- end of bug compatibility + if space.is_true(space.issubtype(w_typ2, w_typ1)): + w_obj1, w_obj2 = w_obj2, w_obj1 + w_left_impl, w_right_impl = w_right_impl, w_left_impl w_res = _invoke_binop(space, w_left_impl, w_obj1, w_obj2) if w_res is not None: Modified: pypy/dist/pypy/objspace/std/test/test_unicodeobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/test/test_unicodeobject.py (original) +++ pypy/dist/pypy/objspace/std/test/test_unicodeobject.py Sat May 31 11:00:30 2008 @@ -554,3 +554,52 @@ '\x00X\x00Y', 'X\x00\x00\x00Y\x00\x00\x00', '\x00\x00\x00X\x00\x00\x00Y'] + + def test_call_special_methods(self): + # xxx not completely clear if these are implementation details or not + assert 'abc'.__add__(u'def') == u'abcdef' + assert u'abc'.__add__(u'def') == u'abcdef' + assert u'abc'.__add__('def') == u'abcdef' + # xxx CPython has no str.__radd__ and no unicode.__radd__ + + def test_str_unicode_concat_overrides(self): + "Test from Jython about being bug-compatible with CPython." + + def check(value, expected): + assert type(value) == type(expected) + assert value == expected + + def _test_concat(t1, t2): + tprecedent = str + if issubclass(t1, unicode) or issubclass(t2, unicode): + tprecedent = unicode + + class SubclassB(t2): + def __add__(self, other): + return SubclassB(t2(self) + t2(other)) + check(SubclassB('py') + SubclassB('thon'), SubclassB('python')) + check(t1('python') + SubclassB('3'), tprecedent('python3')) + check(SubclassB('py') + t1('py'), SubclassB('pypy')) + + class SubclassC(t2): + def __radd__(self, other): + return SubclassC(t2(other) + t2(self)) + check(SubclassC('stack') + SubclassC('less'), t2('stackless')) + check(t1('iron') + SubclassC('python'), SubclassC('ironpython')) + check(SubclassC('tiny') + t1('py'), tprecedent('tinypy')) + + class SubclassD(t2): + def __add__(self, other): + return SubclassD(t2(self) + t2(other)) + + def __radd__(self, other): + return SubclassD(t2(other) + t2(self)) + check(SubclassD('di') + SubclassD('ct'), SubclassD('dict')) + check(t1('list') + SubclassD(' comp'), SubclassD('list comp')) + check(SubclassD('dun') + t1('der'), SubclassD('dunder')) + + _test_concat(str, str) + _test_concat(unicode, unicode) + # the following two cases are really there to emulate a CPython bug. + _test_concat(str, unicode) # uses hack in add__String_Unicode() + _test_concat(unicode, str) # uses hack in descroperation.binop_impl() Modified: pypy/dist/pypy/objspace/std/unicodeobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/unicodeobject.py (original) +++ pypy/dist/pypy/objspace/std/unicodeobject.py Sat May 31 11:00:30 2008 @@ -100,14 +100,28 @@ return W_UnicodeObject(w_left._value + w_right._value) def add__String_Unicode(space, w_left, w_right): + # this function is needed to make 'abc'.__add__(u'def') return + # u'abcdef' instead of NotImplemented. This is what occurs on + # top of CPython. from pypy.objspace.std.unicodetype import unicode_from_string + # XXX fragile implementation detail: for "string + unicode subclass", + # if the unicode subclass overrides __radd__(), then it will be + # called (see test_str_unicode_concat_overrides). This occurs as a + # result of the following call to space.add() in which the first + # argument is a unicode and the second argument a subclass of unicode + # (and thus the usual logic about calling __radd__() first applies). return space.add(unicode_from_string(space, w_left) , w_right) add__Rope_Unicode = add__String_Unicode def add__Unicode_String(space, w_left, w_right): + # this function is needed to make 'abc'.__radd__(u'def') return + # u'defabc', although it's completely unclear if that's necessary + # given that CPython doesn't even have a method str.__radd__(). from pypy.objspace.std.unicodetype import unicode_from_string return space.add(w_left, unicode_from_string(space, w_right)) + # Note about "unicode + string subclass": look for + # "cpython bug compatibility" in descroperation.py add__Unicode_Rope = add__Unicode_String From afa at codespeak.net Sat May 31 15:30:16 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Sat, 31 May 2008 15:30:16 +0200 (CEST) Subject: [pypy-svn] r55443 - in pypy/branch/build-external/pypy/module/zipimport: . test Message-ID: <20080531133016.DD19A2A00E3@codespeak.net> Author: afa Date: Sat May 31 15:30:13 2008 New Revision: 55443 Modified: pypy/branch/build-external/pypy/module/zipimport/interp_zipimport.py pypy/branch/build-external/pypy/module/zipimport/test/test_zipimport.py Log: Correct a bit zipimport for windows: normalize path separators to '/', and (like CPython) search with the full name first, removing elements until a directory or a regular file is found. This handles better the root dir case ("C:" is not a directory), and should be faster as well. Modified: pypy/branch/build-external/pypy/module/zipimport/interp_zipimport.py ============================================================================== --- pypy/branch/build-external/pypy/module/zipimport/interp_zipimport.py (original) +++ pypy/branch/build-external/pypy/module/zipimport/interp_zipimport.py Sat May 31 15:30:13 2008 @@ -309,21 +309,26 @@ w = space.wrap w_ZipImportError = space.getattr(space.getbuiltinmodule('zipimport'), w('ZipImportError')) + + if os.path.sep != '/': + filename = name.replace(os.path.sep, '/') + else: + filename = name ok = False - parts = name.split(os.path.sep) - filename = "" # make annotator happy - for i in range(1, len(parts) + 1): - filename = os.path.sep.join(parts[:i]) - if not filename: - filename = os.path.sep + while True: try: s = os.stat(filename) except OSError: - raise OperationError(w_ZipImportError, space.wrap( - "Cannot find name %s" % (filename,))) - if not stat.S_ISDIR(s.st_mode): + # back up one path element + pos = filename.rfind('/') + if pos == -1: + break + filename = filename[:pos] + continue + + if stat.S_ISREG(s.st_mode): ok = True - break + break if not ok: raise OperationError(w_ZipImportError, space.wrap( "Did not find %s to be a valid zippath" % (name,))) Modified: pypy/branch/build-external/pypy/module/zipimport/test/test_zipimport.py ============================================================================== --- pypy/branch/build-external/pypy/module/zipimport/test/test_zipimport.py (original) +++ pypy/branch/build-external/pypy/module/zipimport/test/test_zipimport.py Sat May 31 15:30:13 2008 @@ -94,13 +94,14 @@ """) def test_cache(self): + import os self.writefile(self, 'x.py', 'y') from zipimport import _zip_directory_cache, zipimporter new_importer = zipimporter(self.zipfile) try: assert zipimporter(self.zipfile) is new_importer finally: - del _zip_directory_cache[self.zipfile] + del _zip_directory_cache[self.zipfile.replace(os.path.sep, '/')] def test_good_bad_arguments(self): from zipimport import zipimporter From afa at codespeak.net Sat May 31 23:48:32 2008 From: afa at codespeak.net (afa at codespeak.net) Date: Sat, 31 May 2008 23:48:32 +0200 (CEST) Subject: [pypy-svn] r55467 - pypy/branch/build-external/pypy/module/zipimport Message-ID: <20080531214832.6451716852C@codespeak.net> Author: afa Date: Sat May 31 23:48:29 2008 New Revision: 55467 Modified: pypy/branch/build-external/pypy/module/zipimport/interp_zipimport.py Log: zipfile store path separators as /, not os.path.sep. Correct zipimport tests on windows. Modified: pypy/branch/build-external/pypy/module/zipimport/interp_zipimport.py ============================================================================== --- pypy/branch/build-external/pypy/module/zipimport/interp_zipimport.py (original) +++ pypy/branch/build-external/pypy/module/zipimport/interp_zipimport.py Sat May 31 23:48:29 2008 @@ -18,9 +18,9 @@ # separators, we need to pretend that we had the os.sep. ENUMERATE_EXTS = unrolling_iterable( - [(True, True, os.path.sep + '__init__.pyc'), - (True, True, os.path.sep + '__init__.pyo'), - (False, True, os.path.sep + '__init__.py'), + [(True, True, ZIPSEP + '__init__.pyc'), + (True, True, ZIPSEP + '__init__.pyo'), + (False, True, ZIPSEP + '__init__.py'), (True, False, '.pyc'), (True, False, '.pyo'), (False, False, '.py')]) @@ -120,7 +120,6 @@ class W_ZipImporter(Wrappable): def __init__(self, space, name, dir, prefix): - self.space = space self.name = name self.dir = dir self.prefix = prefix @@ -132,12 +131,12 @@ return space.wrap(self.prefix) def _find_relative_path(self, filename): + if ZIPSEP != os.path.sep: + filename = filename.replace(os.path.sep, ZIPSEP) if filename.startswith(self.dir.filename): filename = filename[len(self.dir.filename):] - if filename.startswith(os.sep): + if filename.startswith(ZIPSEP): filename = filename[1:] - if ZIPSEP != os.path.sep: - filename = filename.replace(os.path.sep, ZIPSEP) return filename def import_py_file(self, space, modname, filename, buf, pkgpath): @@ -217,7 +216,7 @@ find_module.unwrap_spec = ['self', ObjSpace, str, W_Root] def mangle(self, name): - return name.replace('.', os.path.sep) + return name.replace('.', ZIPSEP) def load_module(self, space, fullname): w = space.wrap @@ -302,8 +301,10 @@ is_package.unwrap_spec = ['self', ObjSpace, str] def getarchive(space, self): - space = self.space - return space.wrap(self.dir.filename) + filename = self.dir.filename + if ZIPSEP != os.path.sep: + filename = filename.replace(ZIPSEP, os.path.sep) + return space.wrap(filename) def descr_new_zipimporter(space, w_type, name): w = space.wrap @@ -347,7 +348,7 @@ raise OperationError(w_ZipImportError, space.wrap( "%s seems not to be a zipfile" % (filename,))) prefix = name[len(filename):] - if prefix.startswith(os.sep): + if prefix.startswith(ZIPSEP): prefix = prefix[1:] w_result = space.wrap(W_ZipImporter(space, name, dir, prefix)) zip_cache.set(filename, w_result)